<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 5.4.0">


  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">



<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.15.4/css/all.min.css" integrity="sha256-mUZM63G8m73Mcidfrv5E+Y61y7a12O5mW4ezU3bxqW4=" crossorigin="anonymous">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/animate.css@3.1.1/animate.min.css" integrity="sha256-PR7ttpcvz8qrF57fur/yAx1qXMFJeJFiA6pSzWi0OIE=" crossorigin="anonymous">

<script class="next-config" data-name="main" type="application/json">{"hostname":"tallgy.gitee.io","root":"/","images":"/images","scheme":"Muse","darkmode":false,"version":"8.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12},"copycode":false,"bookmark":{"enable":false,"color":"#222","save":"auto"},"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"stickytabs":false,"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"fadeInDown","post_body":"fadeInDown","coll_header":"fadeInLeft","sidebar":"fadeInUp"}},"prism":false,"i18n":{"placeholder":"搜索...","empty":"没有找到任何搜索结果：${query}","hits_time":"找到 ${hits} 个搜索结果（用时 ${time} 毫秒）","hits":"找到 ${hits} 个搜索结果"}}</script><script src="/js/config.js"></script>
<meta name="description" content="只是一个知识的搬运工">
<meta property="og:type" content="website">
<meta property="og:title" content="tallgy&#39;s blog">
<meta property="og:url" content="http://tallgy.gitee.io/page/10/index.html">
<meta property="og:site_name" content="tallgy&#39;s blog">
<meta property="og:description" content="只是一个知识的搬运工">
<meta property="og:locale" content="zh_CN">
<meta property="article:author" content="tallgy">
<meta name="twitter:card" content="summary">


<link rel="canonical" href="http://tallgy.gitee.io/page/10/">



<script class="next-config" data-name="page" type="application/json">{"sidebar":"","isHome":true,"isPost":false,"lang":"zh-CN","comments":"","permalink":"","path":"page/10/index.html","title":""}</script>

<script class="next-config" data-name="calendar" type="application/json">""</script>
<title>tallgy's blog</title>
  




  <noscript>
    <link rel="stylesheet" href="/css/noscript.css">
  </noscript>
</head>

<body itemscope itemtype="http://schema.org/WebPage" class="use-motion">
  <div class="headband"></div>

  <main class="main">
    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏" role="button">
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <i class="logo-line"></i>
      <h1 class="site-title">tallgy's blog</h1>
      <i class="logo-line"></i>
    </a>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
    </div>
  </div>
</div>







</div>
        
  
  <div class="toggle sidebar-toggle" role="button">
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
  </div>

  <aside class="sidebar">

    <div class="sidebar-inner sidebar-overview-active">
      <ul class="sidebar-nav">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <div class="sidebar-panel-container">
        <!--noindex-->
        <div class="post-toc-wrap sidebar-panel">
        </div>
        <!--/noindex-->

        <div class="site-overview-wrap sidebar-panel">
          <div class="site-author site-overview-item animated" itemprop="author" itemscope itemtype="http://schema.org/Person">
  <p class="site-author-name" itemprop="name">tallgy</p>
  <div class="site-description" itemprop="description">只是一个知识的搬运工</div>
</div>
<div class="site-state-wrap site-overview-item animated">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
        <a href="/archives/">
          <span class="site-state-item-count">107</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
          <a href="/categories/">
        <span class="site-state-item-count">32</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
          <a href="/tags/">
        <span class="site-state-item-count">74</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>



        </div>
      </div>
    </div>
  </aside>
  <div class="sidebar-dimmer"></div>


    </header>

    
  <div class="back-to-top" role="button" aria-label="返回顶部">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>

<noscript>
  <div class="noscript-warning">Theme NexT works best with JavaScript enabled</div>
</noscript>


    <div class="main-inner index posts-expand">

    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="http://tallgy.gitee.io/2021/10/23/%E9%9A%8F%E7%AC%94/%E7%BD%91%E7%BB%9C/HTTP%E6%A6%82%E8%BF%B0/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="tallgy">
      <meta itemprop="description" content="只是一个知识的搬运工">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="tallgy's blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2021/10/23/%E9%9A%8F%E7%AC%94/%E7%BD%91%E7%BB%9C/HTTP%E6%A6%82%E8%BF%B0/" class="post-title-link" itemprop="url">HTTP概述</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2021-10-23 23:13:22" itemprop="dateCreated datePublished" datetime="2021-10-23T23:13:22+08:00">2021-10-23</time>
    </span>
      <span class="post-meta-item">
        <span class="post-meta-item-icon">
          <i class="far fa-calendar-check"></i>
        </span>
        <span class="post-meta-item-text">更新于</span>
        <time title="修改时间：2023-06-25 16:57:29" itemprop="dateModified" datetime="2023-06-25T16:57:29+08:00">2023-06-25</time>
      </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/%E9%9A%8F%E7%AC%94/" itemprop="url" rel="index"><span itemprop="name">随笔</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h1 id="HTTP概述"><a href="#HTTP概述" class="headerlink" title="HTTP概述"></a>HTTP概述</h1><h2 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h2><p>找不到说啥，直接放个MDN文档</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Overview</span><br></pre></td></tr></table></figure>

<img src="/.io//image-20211024100324347.png" alt="image-20211024100324347" style="zoom:67%;">



<h2 id="版本迭代"><a href="#版本迭代" class="headerlink" title="版本迭代"></a>版本迭代</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Basics_of_HTTP/Evolution_of_HTTP</span><br></pre></td></tr></table></figure>

<h3 id="HTTP-0-9"><a href="#HTTP-0-9" class="headerlink" title="HTTP/0.9"></a>HTTP/0.9</h3><p>也被称为 <strong>单行协议</strong> </p>
<p>请求由单行指令构成，以唯一可用方法<a target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Methods/GET"><code>GET</code></a>开头，其后跟目标资源的路径</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">GET /mypage.html</span><br></pre></td></tr></table></figure>

<p>响应就只包含了响应文档本身，就是HTML文件</p>
<p>并且因为不包含响应头，所以只有HTML文件可以进行传输。</p>
<h3 id="HTTP-1-0"><a href="#HTTP-1-0" class="headerlink" title="HTTP/1.0"></a>HTTP/1.0</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">最大的变化是支持了传输其他文件，默认是短连接，支持GET、POST、 HEAD请求</span><br></pre></td></tr></table></figure>

<ul>
<li>协议版本信息现在会随着每个请求发送（<code>HTTP/1.0</code>被追加到了<code>GET</code>行）。</li>
<li><strong>状态码会在响应开始时发送</strong>，使浏览器能了解请求执行成功或失败，并相应调整行为（如更新或使用本地缓存）。</li>
<li>引入了HTTP头的概念，无论是对于请求还是响应，允许传输元数据，使协议变得非常灵活，更具扩展性。</li>
<li>在新HTTP头的帮助下，具备了传输除纯文本HTML文件以外其他类型文档的能力（感谢<a target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Content-Type"><code>Content-Type</code></a>头）。</li>
</ul>
<p><strong>默认是短连接，一次请求会建立一次TCP连接，请求结束就断开。</strong>可以通过一个 <code>Connection: keep-alive</code>字段使服务器不关闭连接。服务器同时也会响应这个字段。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">GET /mypage.html HTTP/1.0</span><br><span class="line">User-Agent: NCSA_Mosaic/2.0 (Windows 3.1)</span><br><span class="line"></span><br></pre></td></tr></table></figure>



<h3 id="HTTP-1-1"><a href="#HTTP-1-1" class="headerlink" title="HTTP/1.1"></a>HTTP/1.1</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">最大的变化就是支持了持久连接，默认长连接。不同自己声明 `Connection: keep-alive` ，增加了 `HOST` ，增加了请求方式，支持断点续传功能。</span><br></pre></td></tr></table></figure>

<ul>
<li>连接可以复用，节省了多次打开TCP连接加载网页文档资源的时间。</li>
<li>增加管线化技术，允许在第一个应答被完全发送之前就发送第二个请求，以降低通信延迟。</li>
<li>支持响应分块。</li>
<li>引入额外的缓存控制机制。</li>
<li>引入内容协商机制，包括语言，编码，类型等，并允许客户端和服务器之间约定以最合适的内容进行交换。</li>
<li>感谢<a target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Host"><code>Host</code></a>头，能够使不同域名配置在同一个IP地址的服务器上。</li>
</ul>
<p><strong>Host</strong> 请求头指明了请求将要发送到的服务器主机名和端口号。</p>
<p>如果没有包含端口号，会自动使用被请求服务的默认端口（比如HTTPS URL使用443端口，HTTP URL使用80端口）。</p>
<p>所有HTTP/1.1 请求报文中必须包含一个<code>Host</code>头字段。对于缺少<code>Host</code>头或者含有超过一个<code>Host</code>头的HTTP/1.1 请求，可能会收到<a target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status/400"><code>400</code></a>（Bad Request）状态码。</p>
<p>所有请求都是通过一个连接实现的。就是持久连接。服务器发现对方一段时间没有活动，就可以主动关闭连接。不过，规范的做法是，客户端在最后一个请求时，发送<code>Connection: close</code>，明确要求服务器关闭TCP连接。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">GET /en-US/docs/Glossary/Simple_header HTTP/1.1</span><br><span class="line">Host: developer.mozilla.org</span><br><span class="line">User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:50.0) Gecko/20100101 Firefox/50.0</span><br><span class="line">Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8</span><br><span class="line">Accept-Language: en-US,en;q=0.5</span><br><span class="line">Accept-Encoding: gzip, deflate, br</span><br><span class="line">Referer: https://developer.mozilla.org/en-US/docs/Glossary/Simple_header</span><br><span class="line"></span><br></pre></td></tr></table></figure>



<h3 id="HTTP-2-0"><a href="#HTTP-2-0" class="headerlink" title="HTTP/2.0"></a>HTTP/2.0</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">最大的区别，协议为二进制协议，服务器主动推送，以及 headers 压缩</span><br></pre></td></tr></table></figure>

<ul>
<li>HTTP/2是二进制协议而不是文本协议。不再可读，也不可无障碍的手动创建，改善的优化技术现在可被实施。</li>
<li>这是一个复用协议。并行的请求能在同一个链接中处理，移除了HTTP/1.x中顺序和阻塞的约束。</li>
<li>压缩了headers。因为headers在一系列请求中常常是相似的，其移除了重复和传输重复数据的成本。</li>
<li>其允许服务器在客户端缓存中填充数据，通过一个叫服务器推送的机制来提前请求。</li>
</ul>
<h3 id="服务器推送方式"><a href="#服务器推送方式" class="headerlink" title="服务器推送方式"></a>服务器推送方式</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://www.ruanyifeng.com/blog/2017/05/server-sent_events.html</span><br></pre></td></tr></table></figure>

<p><strong>WebSockets</strong></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://developer.mozilla.org/zh-CN/docs/Web/API/WebSockets_API</span><br></pre></td></tr></table></figure>

<p><strong>Server-sent events</strong></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://developer.mozilla.org/zh-CN/docs/Web/API/Server-sent_events</span><br></pre></td></tr></table></figure>



<h2 id="连接管理"><a href="#连接管理" class="headerlink" title="连接管理"></a>连接管理</h2><p>HTTP/1.x有三个，HTTP/2新增了其他的连接管理模型</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Connection_management_in_HTTP_1.x</span><br></pre></td></tr></table></figure>



<p>HTTP/1.x的三个连接</p>
<p>短连接，长连接，流水线</p>
<img src="/.io//image-20211024104204389.png" alt="image-20211024104204389" style="zoom:67%;">



<h3 id="短连接"><a href="#短连接" class="headerlink" title="短连接"></a>短连接</h3><p>​        每一个 HTTP 请求都由它自己独立的连接完成；这意味着发起每一个 HTTP 请求之前都会有一次 TCP 握手，而且是连续不断的。</p>
<p>​        简单来说就是每次请求都要建立连接，请求结束关闭连接，造成了大量的连接时间的浪费。</p>
<p>​        这是 HTTP/1.0 的默认模型(如果没有指定 <a target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Connection"><code>Connection</code></a> 协议头，或者是值被设置为 <code>close</code>)。而在 HTTP/1.1 中，只有当 <a target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Connection"><code>Connection</code></a> 被设置为 <code>close</code> 时才会用到这个模型。</p>
<h3 id="长连接"><a href="#长连接" class="headerlink" title="长连接"></a>长连接</h3><p>​        在HTTP/1.1被设计出来之前：<code>Connection: keep-alive</code>被作为一个请求头，做成了长连接的效果。</p>
<p>​        为了缓解这些问题，<em>长连接</em> 的概念便被设计出来了，甚至在 HTTP/1.1 之前。或者这被称之为一个 <em>keep-alive</em> 连接。</p>
<h3 id="流水线"><a href="#流水线" class="headerlink" title="流水线"></a>流水线</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">HTTP 流水线在现代浏览器中并不是默认被启用的：</span><br><span class="line">	Web 开发者并不能轻易的遇见和判断那些搞怪的代理服务器的各种莫名其妙的行为。</span><br><span class="line">	正确的实现流水线是复杂的：传输中的资源大小，多少有效的 RTT 会被用到，还有有效带宽，流水线带来的改善有多大的影响范围。不知道这些的话，重要的消息可能被延迟到不重要的消息后面。这个重要性的概念甚至会演变为影响到页面布局！因此 HTTP 流水线在大多数情况下带来的改善并不明显。</span><br><span class="line">	流水线受制于 HOL 问题。</span><br><span class="line">由于这些原因，流水线已经被更好的算法给代替，如 multiplexing，已经用在 HTTP/2。</span><br></pre></td></tr></table></figure>

<p>简单理解就是说，直接发送连续的请求，不需要等待每次的响应。</p>
<h3 id="域名分片"><a href="#域名分片" class="headerlink" title="域名分片"></a>域名分片</h3><p>简单的理解就是为域名多建立几个连接。以实现并发请求。但是HTTP/2支持客户端的并发请求</p>

      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="http://tallgy.gitee.io/2021/10/22/%E6%B5%8F%E8%A7%88%E5%99%A8/%E6%B5%8F%E8%A7%88%E5%99%A8%E7%BC%93%E5%AD%98%E7%AD%96%E7%95%A5/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="tallgy">
      <meta itemprop="description" content="只是一个知识的搬运工">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="tallgy's blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2021/10/22/%E6%B5%8F%E8%A7%88%E5%99%A8/%E6%B5%8F%E8%A7%88%E5%99%A8%E7%BC%93%E5%AD%98%E7%AD%96%E7%95%A5/" class="post-title-link" itemprop="url">浏览器缓存策略</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2021-10-22 21:43:10" itemprop="dateCreated datePublished" datetime="2021-10-22T21:43:10+08:00">2021-10-22</time>
    </span>
      <span class="post-meta-item">
        <span class="post-meta-item-icon">
          <i class="far fa-calendar-check"></i>
        </span>
        <span class="post-meta-item-text">更新于</span>
        <time title="修改时间：2023-06-25 16:57:29" itemprop="dateModified" datetime="2023-06-25T16:57:29+08:00">2023-06-25</time>
      </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/%E9%9A%8F%E7%AC%94/" itemprop="url" rel="index"><span itemprop="name">随笔</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h1 id="浏览器缓存策略"><a href="#浏览器缓存策略" class="headerlink" title="浏览器缓存策略"></a>浏览器缓存策略</h1><p><strong>参考文章</strong></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">https://juejin.cn/post/6844903757872889870</span><br><span class="line">MDN</span><br><span class="line">https://juejin.cn/post/6844903737538920462</span><br></pre></td></tr></table></figure>



<p><strong>先说一下什么是缓存</strong></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">缓存就是会将一些不会经常更改的图片文件等资源存储下来，下次访问的时候会优先读取本地的资源进行显示，这样既能减轻服务器的负载，也能加快页面的显示。</span><br><span class="line">这时可能就可能会问，那如果资源有了改变怎么办，所以这时候就有了强缓存和协商缓存两种。</span><br></pre></td></tr></table></figure>



<p><strong>浏览器缓存策略分为</strong></p>
<p>​    <strong>强缓存</strong></p>
<p>​        强缓存就是直接从本地进行读取，不需要向服务器端进行获取资源。因此很快。</p>
<p>​        在命中强缓存的情况下，状态码为 200，但是size显示from disk cache或from memory cache</p>
<p>​    <strong>协商缓存</strong></p>
<p>​        协商缓存就是会请求，但是会将一个文件的信息加入到请求头，然后服务器端进行判断，来决定是否要更新浏览器的资源。</p>
<p>​        会将 <code>Last-Modified</code> 和 <code>Etag</code> 放入请求头，然后服务器就会进行比对，如果命中协商缓存，状态码为304。否则会将资源传输过来。</p>
<h2 id="强缓存"><a href="#强缓存" class="headerlink" title="强缓存"></a>强缓存</h2><p>在进行请求的时候，不会向服务器发送请求，直接从缓存中读取资源，但是状态码是200</p>
<p>如何进行强缓存，简单来说就是我们请求资源之后，服务器会返回一个请求头。浏览器后续就会根据这个请求头进行判断是否命中强缓存。</p>
<h3 id="请求头"><a href="#请求头" class="headerlink" title="请求头"></a>请求头</h3><p>​        对于强缓存的请求头，有 <strong>Expires</strong> 和 <strong>Cache-Control</strong>，但是因为<strong>Cache-Control</strong> 是HTTP/1.1的产物，所以，优先级高于 Expires。</p>
<h4 id="Expires"><a href="#Expires" class="headerlink" title="Expires"></a>Expires</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Expires</span><br></pre></td></tr></table></figure>

<p>HTTP/1.0</p>
<p>​    缓存过期时间，用来指定资源到期的时间。</p>
<p>​        缺点，是通过本地时间进行的判断。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Expires: Wed, 21 Oct 2015 07:28:00 GMT</span><br></pre></td></tr></table></figure>

<p><strong>注：</strong></p>
<p>​    如果在<code>Cache-Contro</code>响应头设置了<code>max-age</code>或者<code>s-max-age</code>指令，那么<code>Expires</code>头会被忽悠。</p>
<h4 id="Cache-Control"><a href="#Cache-Control" class="headerlink" title="Cache-Control"></a>Cache-Control</h4><p>HTTP/1.1</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Cache-Control</span><br></pre></td></tr></table></figure>

<p><strong>语法</strong>：</p>
<ul>
<li>不区分大小写，但建议使用小写。</li>
<li>多个指令以逗号分隔。</li>
<li>具有可选参数，可以用令牌或者带引号的字符串语法。</li>
</ul>
<p><strong>默认值：private</strong></p>
<p><strong>指令</strong>：</p>
<p><strong>可缓存性指令：</strong></p>
<p><strong>public：</strong></p>
<p>​        表明响应可以被任何对象（包括：发送请求的客户端，代理服务器，等等）缓存，即使是通常不可缓存的内容。</p>
<p>​        （例如：1.该响应没有<code>max-age</code>指令或<code>Expires</code>消息头；</p>
<p>​                        2. 该响应对应的请求方法是 <a target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Methods/POST">POST</a> 。）</p>
<p><strong>private：</strong></p>
<p>​        表明响应只能被单个用户缓存，不能作为共享缓存（即代理服务器不能缓存它）。私有缓存可以缓存响应内容。</p>
<p>​        比如：对应用户的本地浏览器。</p>
<p><strong>no-cache</strong>:</p>
<p>​        在发布缓存副本之前，强制要求缓存把请求提交给原始服务器进行验证(协商缓存验证)。</p>
<p><strong>no-store</strong>：</p>
<p>​        缓存不应存储有关客户端请求或服务器响应的任何内容，即不使用任何缓存。</p>
<p><strong>到期：</strong></p>
<p><strong>max-age</strong>：</p>
<p>​        设置缓存存储的最大周期，超过这个时间缓存被认为过期(单位秒)。与<code>Expires</code>相反，时间是相对于请求的时间。</p>
<p><strong>s-maxage</strong>：</p>
<p>​        覆盖<code>max-age</code>或者<code>Expires</code>头，但是仅适用于共享缓存(比如各个代理)，私有缓存会忽略它。</p>
<p><strong>max-stale</strong>：</p>
<p>​        表明客户端愿意接收一个已经过期的资源。可以设置一个可选的秒数，表示响应不能已经过时超过该给定的时间。</p>
<p><strong>min-fresh</strong>：</p>
<p>​        表示客户端希望获取一个能在指定的秒数内保持其最新状态的响应。</p>
<p><strong>重新验证与加载：</strong></p>
<p><strong>must-revalidate</strong>：</p>
<p>​        一旦资源过期（比如已经超过<code>max-age</code>），在成功向原始服务器验证之前，缓存不能用该资源响应后续请求。</p>
<img src="/.io//image-20211023161739229.png" alt="image-20211023161739229" style="zoom:67%;">

<p>图片来源</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://juejin.cn/post/6844903757872889870</span><br></pre></td></tr></table></figure>



<p><strong>需要进行重新验证，这个就是会进行协商缓存：</strong></p>
<p>​        指定 <code>no-cache</code> 或 <code>max-age=0, must-revalidate</code> 表示客户端可以缓存资源，每次使用缓存资源前都必须重新验证其有效性。这意味着每次都会发起 HTTP 请求，但当缓存内容仍有效时可以跳过 HTTP 响应体的下载。</p>
<p><strong>注意：</strong></p>
<p>​    如果服务器关闭或失去连接，下面的指令可能会造成使用缓存。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Cache-Control: max-age=0</span><br></pre></td></tr></table></figure>



<h3 id="在强缓存时间内如何更新资源"><a href="#在强缓存时间内如何更新资源" class="headerlink" title="在强缓存时间内如何更新资源"></a>在强缓存时间内如何更新资源</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://juejin.cn/post/6844903737538920462#heading-5</span><br></pre></td></tr></table></figure>

<p>虽然强缓存很好，但是有一个问题，如果在强缓存时间内，我的文件资源发生了更新，那该怎么解决呢？<code>（这个是我面试的时候问到的，一下把我人问傻了。）</code></p>
<p>这里我后面去了解了：</p>
<p>​    简单来说就是对于资源文件需要在发生了改变之后，可以让客户端再请求一次，方法就是将文件的名字在每次修改之后会发生改变，所以每次修改了之后，客户端要请求的文件名发生了改变，就会重新再进行一次请求了。这里对于文件名的方式使用<code>hash</code>。</p>
<p>​    HTML：使用协商缓存，因为里面会存储资源文件的路径，在每次更新之后里面的路径需要修改，所以使用协商缓存更合理。</p>
<p>​    对于　CSS／JS／图片：使用强缓存，对于一个文件名带上一个 hash 值。在每次文件进行了修改之后，名字后面的hash就会发生改变。所以客户端就会重新请求。</p>
<h2 id="协商缓存"><a href="#协商缓存" class="headerlink" title="协商缓存"></a>协商缓存</h2><p>​        会在请求头加上：<code>If-None-Match</code>和<code>If-Modified-Since</code></p>
<p>​        分别对应了服务器响应头的：<code>ETag</code> 和  <code>Last-Modified</code></p>
<p>ETag 优先级高于 Last-Modified</p>
<h3 id="If-Modified-Since-与-Last-Modified："><a href="#If-Modified-Since-与-Last-Modified：" class="headerlink" title="If-Modified-Since 与  Last-Modified："></a><strong>If-Modified-Since</strong> 与  <strong>Last-Modified</strong>：</h3><p><strong>Last-Modified</strong>：</p>
<p>​    这个是服务器端的返回的响应头。</p>
<p><strong>If-Modified-Since</strong>：</p>
<p>​    这个是客户端的请求的请求头。</p>
<h4 id="Last-Modified："><a href="#Last-Modified：" class="headerlink" title="Last-Modified："></a><strong>Last-Modified</strong>：</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Last-Modified</span><br></pre></td></tr></table></figure>

<p>​        这个是根据上一次请求资源时，服务器所返回的<strong>Last-Modified</strong>，这个作为一个响应的头部。其中包含源头服务器认定的资源做出修改的日期及时间</p>
<p>​        包含有  <a target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/If-Modified-Since"><code>If-Modified-Since</code></a> 或 <a target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/If-Unmodified-Since"><code>If-Unmodified-Since</code></a> 首部的条件请求会使用这个字段。 </p>
<h4 id="If-Modified-Since："><a href="#If-Modified-Since：" class="headerlink" title="If-Modified-Since："></a><strong>If-Modified-Since</strong>：</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/If-Modified-Since</span><br></pre></td></tr></table></figure>

<p>​        服务器只在所请求的资源在给定的日期时间之后对内容进行过修改的情况下才会将资源返回，状态码为 <a target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status/200"><code>200</code></a> 。</p>
<p>​        如果请求的资源从那时起未经修改，那么返回一个不带有消息主体的 <a target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status/304"><code>304</code></a> 响应，而在 <a target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Last-Modified"><code>Last-Modified</code></a> 首部中会带有上次修改时间。<strong>（注：虽然返回了304，但是会有last-modified的头部返回，因此浏览器下次请求时，会使用的是此时服务器端返回过来的last-modified，而不是以前的。）</strong></p>
<p>​        <code>If-Modified-Since</code> 只可以用在 <a target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Methods/GET"><code>GET</code></a> 或 <a target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Methods/HEAD"><code>HEAD</code></a> 请求中。</p>
<p>​        当与 <a target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/If-None-Match"><code>If-None-Match</code></a> 一同出现时，它（**<code>If-Modified-Since</code>**）会被忽略掉，除非服务器不支持 <code>If-None-Match</code>。</p>
<p><strong>If-Unmodified-Since：</strong></p>
<p>​        这个我没有了解。</p>
<p><strong>使用上面这个的弊端：</strong></p>
<p>​        对于没有进行修改，但是有过保存导致 Last-Modified 被修改，无法命中。</p>
<p>​        这个只能以秒计时，所以对于秒以内的修改文件，不能返回。</p>
<h3 id="If-None-Match-和-ETag"><a href="#If-None-Match-和-ETag" class="headerlink" title="If-None-Match 和 ETag"></a>If-None-Match 和 ETag</h3><p><strong>ETag</strong>：</p>
<p>​    这个是服务器端的返回的响应头。</p>
<p><strong>If-None-Match</strong>：</p>
<p>​    这个是客户端的请求的请求头。</p>
<h4 id="ETag："><a href="#ETag：" class="headerlink" title="ETag："></a><strong>ETag</strong>：</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/ETag</span><br></pre></td></tr></table></figure>

<p>简单来说就是一个唯一标识资源的一个特殊符号，</p>
<p>通常计算方式是：</p>
<p>​    <strong>使用内容的散列，最后修改时间戳的哈希值，或简单地使用版本号</strong></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">https://juejin.cn/post/6844903737538920462</span><br><span class="line">这里有将比较详细的计算方式，我这里就不做过多的说明。</span><br></pre></td></tr></table></figure>



<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ETag: &quot;33a64df551425fcc55e4d42a148795d9f25f89d4&quot;</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">作用：</span><br><span class="line">	避免空中碰撞</span><br><span class="line">	缓存未更改的资源，就是304.</span><br></pre></td></tr></table></figure>



<h5 id="避免空中碰撞"><a href="#避免空中碰撞" class="headerlink" title="避免空中碰撞"></a>避免空中碰撞</h5><p>MDN上有说有这句话：</p>
<p>​    <strong>而如果内容发生了变化，使用ETag有助于防止资源的同时更新相互覆盖（“空中碰撞”）</strong></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/ETag#避免“空中碰撞”</span><br></pre></td></tr></table></figure>

<p>大概的意思就是说，</p>
<p>​        我在客户端进行编辑共享文档时<code>（共享文档就是说可以被多人查看和编辑的）</code>，最开始拿到的文档是最新的。</p>
<p>​        但是在编辑的过程中，可能别人也有编辑，但是比我上传的早，所以，在我准备上传一个共享文档时，服务器端的文档已经被别人修改过了，但是此时我的客户端的文档因为没有重新进行请求，所以还是没有被修改过的，</p>
<p>​        此时如果没有先进行一次判断 ETag 值的话，就会发生相互覆盖，这个就是空中碰撞。</p>
<p>​        避免就是会先进行 ETag 匹配检查是否为最新版，否则报 412 前提条件失败错误。</p>
<p><code>（此时这个 ETag 会放在 If-Match 的请求头中。）</code></p>
<p><strong>注：</strong></p>
<p>​        如果给定URL中的资源更改，则一定要生成新的 Etag 值。 因此 Etags 类似于指纹，也可能被某些服务器用于跟踪。 比较 etags 能快速确定此资源是否变化，但也可能被跟踪服务器永久存留。<strong>（我能理解到 ETag 可能用于快速比较一个文件是否发生过修改，因为他是一个文根据文件的相关信息进行的一个算法生成的一个值，但是我不清楚什么是会被跟踪服务器存留）</strong></p>
<h5 id="缓存未更改的资源"><a href="#缓存未更改的资源" class="headerlink" title="缓存未更改的资源"></a>缓存未更改的资源</h5><p>​        对于用户访问一个URL时，显示了资源过期且不可用，客户端就发送 ETag 的值 作为 If-None-Match 的请求头，如果资源没有更改，那么服务器将会返回不带响应体的 304 状态。</p>
<h4 id="If-None-Match："><a href="#If-None-Match：" class="headerlink" title="If-None-Match："></a><strong>If-None-Match</strong>：</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/If-None-Match</span><br></pre></td></tr></table></figure>

<p><code>If-None-Match</code> 和 <code>If-Match</code> 的区别</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://datatracker.ietf.org/doc/html/rfc7232#section-3.1</span><br></pre></td></tr></table></figure>

<p>If-None-Match</p>
<p>​    使用的是 弱比较算法。</p>
<p>​    常用于 GET 请求的，请求最新资源的方式</p>
<p>If-Match</p>
<p>​    使用的是 强比较算法。</p>
<p>​    常用于 POST  PUT，DELETE 状态改变方法，防止多个用户同时操作的意外覆盖。</p>
<h2 id="后端设置方式"><a href="#后端设置方式" class="headerlink" title="后端设置方式"></a>后端设置方式</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">参考文章</span><br><span class="line">https://juejin.cn/post/6844903737538920462#heading-11</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">res.setHeader(&#x27;Cache-Control&#x27;, &#x27;public, max-age=xxx&#x27;);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">res.setHeader(&#x27;Cache-Control&#x27;, &#x27;public, max-age=0&#x27;);</span><br><span class="line">res.setHeader(&#x27;Last-Modified&#x27;, xxx);</span><br><span class="line">res.setHeader(&#x27;ETag&#x27;, xxx);</span><br></pre></td></tr></table></figure>





<h2 id="最后，重新来一遍浏览器缓存过程"><a href="#最后，重新来一遍浏览器缓存过程" class="headerlink" title="最后，重新来一遍浏览器缓存过程"></a>最后，重新来一遍浏览器缓存过程</h2><p><strong>第一次请求</strong></p>
<p>浏览器进行请求，发现缓存没有这个文件</p>
<p>向服务器进行请求，获得文件，并带上响应头：</p>
<p>​    属于强缓存的：Cache-Control，Expires</p>
<p>​    属于协商缓存的：ETag，Last-Modified</p>
<p>浏览器接收到了文件，并将文件和这些响应头缓存下来，下次使用。</p>
<p><strong>强缓存</strong></p>
<p>浏览器进行请求，发现缓存存在这个文件</p>
<p>浏览器缓存查看该次请求是否命中强缓存（就是没有超过文件缓存过期时间）</p>
<p>命中强缓存，直接从本地读取，状态码：200</p>
<p><strong>协商缓存</strong></p>
<p>浏览器进行请求，发现缓存存在这个文件</p>
<p>浏览器缓存查看该次请求是否命中强缓存，</p>
<p>没有命中强缓存，将 ETag 和 Last-Modified 的值放入请求头，</p>
<p>​    为 If-None-Match 和 If-Modified-Since，发送给服务器</p>
<p>服务器接收到请求后，查看是否命中协商缓存，</p>
<p>发现命中协商缓存，服务器会返回状态码 304，没有响应体</p>
<p>​    并将响应头的 Last-Modified 和 ETag 的值设置为文件的值，返回</p>
<p>客户端接收到服务器的 304 响应，并将 ETag 和 Last-Modified 存储下来。</p>
<p><strong>简单来说：</strong></p>
<p>​    就是第一次的文件请求会正常的返回，第二次会先看看能不能命中强缓存，如果能直接读取本地的，如果不能则看看能不能命中协商缓存，如果命中，则还是读取本地的文件，如果都没有命中，那么就会使用新的文件。</p>
<p>这里<strong>对于一个文件如何在强缓存期间进行更新</strong>也有说明：就是会对文件名进行hash计算，修改过的文件的hash值不一样，所以对于浏览器来说，这个文件名不一样，不是一个文件，需要重新请求。</p>

      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="http://tallgy.gitee.io/2021/10/21/HTML/%E5%9D%97%E7%8E%AF%E5%A2%83%E4%B8%8A%E4%B8%8B%E6%96%87/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="tallgy">
      <meta itemprop="description" content="只是一个知识的搬运工">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="tallgy's blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2021/10/21/HTML/%E5%9D%97%E7%8E%AF%E5%A2%83%E4%B8%8A%E4%B8%8B%E6%96%87/" class="post-title-link" itemprop="url">块环境上下文(BFC)</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2021-10-21 22:49:56" itemprop="dateCreated datePublished" datetime="2021-10-21T22:49:56+08:00">2021-10-21</time>
    </span>
      <span class="post-meta-item">
        <span class="post-meta-item-icon">
          <i class="far fa-calendar-check"></i>
        </span>
        <span class="post-meta-item-text">更新于</span>
        <time title="修改时间：2023-06-25 16:57:29" itemprop="dateModified" datetime="2023-06-25T16:57:29+08:00">2023-06-25</time>
      </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/HTML/" itemprop="url" rel="index"><span itemprop="name">HTML</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h1 id="块环境上下文（BFC）"><a href="#块环境上下文（BFC）" class="headerlink" title="块环境上下文（BFC）"></a>块环境上下文（BFC）</h1><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">https://developer.mozilla.org/zh-CN/docs/Web/Guide/CSS/Block_formatting_context</span><br><span class="line">https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_Flow_Layout/Intro_to_formatting_contexts</span><br></pre></td></tr></table></figure>



<p><strong>什么是BFC</strong></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">块格式化上下文（Block Formatting Context，BFC） 是Web页面的可视CSS渲染的一部分，是块盒子的布局过程发生的区域，也是浮动元素与其他元素交互的区域。</span><br></pre></td></tr></table></figure>

<p><strong>有什么作用</strong></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">解决外边距合并：</span><br><span class="line">	首先，外边距合并的原因是因为在同一个BFC下的结果，所以我们可以针对不同的</span><br><span class="line">	对于不同的BFC也不会造成外边距和合并。所以可以使用BFC来解决外边距合并的问题。</span><br><span class="line">清除浮动：</span><br><span class="line">	可以清除浮动，对于清除浮动，只能清除同一BFC的浮动。</span><br><span class="line">自适应两栏布局：</span><br><span class="line">	可以做一个横向的两栏布局，一个宽度固定作为一个BFC，另一个做成另一个BFC。</span><br></pre></td></tr></table></figure>



<h2 id="创建方式"><a href="#创建方式" class="headerlink" title="创建方式"></a>创建方式</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">根元素（&lt;html&gt;）</span><br><span class="line">浮动元素（元素的 float 不是 none）</span><br><span class="line">绝对定位元素（元素的 position 为 absolute 或 fixed）</span><br><span class="line">行内块元素（元素的 display 为 inline-block）</span><br><span class="line">表格单元格（元素的 display 为 table-cell，HTML表格单元格默认为该值）</span><br><span class="line">表格标题（元素的 display 为 table-caption，HTML表格标题默认为该值）</span><br><span class="line">匿名表格单元格元素（元素的 display 为 table、table-row、 table-row-group、table-header-group、table-footer-group（分别是HTML table、row、tbody、thead、tfoot 的默认属性）或 inline-table）</span><br><span class="line">overflow 计算值(Computed)不为 visible 的块元素</span><br><span class="line">display 值为 flow-root 的元素</span><br><span class="line">contain 值为 layout、content 或 paint 的元素</span><br><span class="line">弹性元素（display 为 flex 或 inline-flex 元素的直接子元素）</span><br><span class="line">网格元素（display 为 grid 或 inline-grid 元素的直接子元素）</span><br><span class="line">多列容器（元素的 column-count 或 column-width (en-US) 不为 auto，包括 column-count 为 1）</span><br><span class="line">column-span 为 all 的元素始终会创建一个新的BFC，即使该元素没有包裹在一个多列容器中（标准变更，Chrome bug）。</span><br></pre></td></tr></table></figure>



<h2 id="常用的-BFC-方式"><a href="#常用的-BFC-方式" class="headerlink" title="常用的 BFC 方式"></a>常用的 BFC 方式</h2><p>HTML根元素</p>
<p>浮动， 不能为 <code>none</code></p>
<p>绝对定位， 包括 <code>absolute </code>和 <code>fixed</code></p>
<p>表格    包括，表格布局和表格元素</p>
<p>overflow    计算值不为 <code>visible</code> ，这里说的是计算值</p>
<p>弹性布局    <code>flex</code></p>
<p>网格布局    <code>grid</code></p>
<p>​        <code>display: flow-root</code>，一个新的 <code>display</code> 属性的值，它可以创建无副作用的 BFC。在父级块中使用 <code>display: flow-root</code> 可以创建新的 BFC。</p>
<p>​        给 <code>&lt;div&gt;</code> <code>display: flow-root</code> 属性后，<code>&lt;div&gt;</code> 中的所有内容都会参与 BFC，浮动的内容不会从底部溢出。</p>
<h3 id="解决外边距合并"><a href="#解决外边距合并" class="headerlink" title="解决外边距合并"></a>解决外边距合并</h3><p>这个我前面有写有，并且这个只需要不处于同一个BFC就可以有效果。所以这里不做过多说明，就简单的贴一个代码就行。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html lang=&quot;zh&quot;&gt;</span><br><span class="line">&lt;head&gt;</span><br><span class="line">  &lt;meta charset=&quot;UTF-8&quot;&gt;</span><br><span class="line">  &lt;title&gt;Title&lt;/title&gt;</span><br><span class="line">  &lt;style&gt;</span><br><span class="line">    .f &#123;</span><br><span class="line">      display: inline-block;</span><br><span class="line">      background-color: red;</span><br><span class="line">      height: 90px;</span><br><span class="line">      width: 100px;</span><br><span class="line">      margin-bottom: 20px;</span><br><span class="line">    &#125;</span><br><span class="line">    .c &#123;</span><br><span class="line">      margin-top: 20px;</span><br><span class="line">      height: 100px;</span><br><span class="line">      width: 200px;</span><br><span class="line">      background-color: blue;</span><br><span class="line">    &#125;</span><br><span class="line">  &lt;/style&gt;</span><br><span class="line"></span><br><span class="line">&lt;/head&gt;</span><br><span class="line">&lt;body&gt;</span><br><span class="line">&lt;div class=&quot;f&quot;&gt;&lt;/div&gt;</span><br><span class="line">&lt;div class=&quot;c&quot;&gt;&lt;/div&gt;</span><br><span class="line">&lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure>



<h3 id="清除浮动"><a href="#清除浮动" class="headerlink" title="清除浮动"></a>清除浮动</h3><p>​        从下面的例子可以看出。</p>
<p>​        从结果可以看到，当一个元素创建了一个BFC之后，其内部的所有元素都会影响。对于根元素f（red），子元素c（blue），子子元素cc（black）。red的高度被其black所影响。而因为blue没有形成一个BFC，所以虽然black属于blue的子元素，但是blue没有将高度撑开为 black 的高度。</p>
<p><strong>注意：</strong>使用clear清除浮动，不是BFC的效果。因为我们可以直接对父元素使用clear发现并不会撑开盒子，所以并没有产生BFC。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html lang=&quot;zh&quot;&gt;</span><br><span class="line">&lt;head&gt;</span><br><span class="line">  &lt;meta charset=&quot;UTF-8&quot;&gt;</span><br><span class="line">  &lt;title&gt;Title&lt;/title&gt;</span><br><span class="line">  &lt;style&gt;</span><br><span class="line">    .f &#123;</span><br><span class="line">      display: flow-root;</span><br><span class="line">      background-color: red;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    .c &#123;</span><br><span class="line">      /*float: left;*/</span><br><span class="line">      height: 100px;</span><br><span class="line">      width: 200px;</span><br><span class="line">      background-color: blue;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    .cc &#123;</span><br><span class="line">      float: left;</span><br><span class="line">      height: 300px;</span><br><span class="line">      width: 100px;</span><br><span class="line">      background-color: black;</span><br><span class="line">    &#125;</span><br><span class="line">  &lt;/style&gt;</span><br><span class="line"></span><br><span class="line">&lt;/head&gt;</span><br><span class="line">&lt;body&gt;</span><br><span class="line">&lt;div class=&quot;f&quot;&gt;</span><br><span class="line">  &lt;div class=&quot;c&quot;&gt;</span><br><span class="line">    &lt;div class=&quot;cc&quot;&gt;&lt;/div&gt;</span><br><span class="line">  &lt;/div&gt;</span><br><span class="line">&lt;/div&gt;</span><br><span class="line"></span><br><span class="line">&lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure>

<p>结果</p>
<img src="/.io//image-20211022110540794.png" alt="image-20211022110540794" style="zoom:33%;">







<p>注意点：如果设置了高度，那么父元素则不会进行扩张。</p>
<p>以及对一个元素的 before和 after伪类进行了 BFC ，并不会将 BFC 给到该元素上。</p>
<h3 id="两栏布局"><a href="#两栏布局" class="headerlink" title="两栏布局"></a>两栏布局</h3><p>就是，先指定一个的宽度，然后令其浮动，此时第二个的盒子将会位于第一个下面，然后，在将第二个盒子设置成一个BFC，所以就会出现他们并排一行，并且第二个盒子不会换行，然后因为默认占比的100%宽度，所以就会有一个自适应的效果。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html lang=&quot;zh&quot;&gt;</span><br><span class="line">&lt;head&gt;</span><br><span class="line">  &lt;meta charset=&quot;UTF-8&quot;&gt;</span><br><span class="line">  &lt;title&gt;Title&lt;/title&gt;</span><br><span class="line">  &lt;style&gt;</span><br><span class="line">    .left &#123;</span><br><span class="line">      float: left;</span><br><span class="line">      height: 100px;</span><br><span class="line">      width: 200px;</span><br><span class="line">      background-color: red;</span><br><span class="line">    &#125;</span><br><span class="line">    .right &#123;</span><br><span class="line">      overflow: hidden;</span><br><span class="line">      height: 300px;</span><br><span class="line">      background-color: blue;</span><br><span class="line">    &#125;</span><br><span class="line">  &lt;/style&gt;</span><br><span class="line">&lt;/head&gt;</span><br><span class="line">&lt;body&gt;</span><br><span class="line">&lt;div class=&quot;left&quot;&gt;&lt;/div&gt;</span><br><span class="line">&lt;div class=&quot;right&quot;&gt;&lt;/div&gt;</span><br><span class="line">&lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure>



<img src="/.io//image-20211022161542404.png" alt="image-20211022161542404" style="zoom:33%;">


      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="http://tallgy.gitee.io/2021/10/20/CSS/%E5%A4%96%E8%BE%B9%E8%B7%9D%E5%90%88%E5%B9%B6/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="tallgy">
      <meta itemprop="description" content="只是一个知识的搬运工">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="tallgy's blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2021/10/20/CSS/%E5%A4%96%E8%BE%B9%E8%B7%9D%E5%90%88%E5%B9%B6/" class="post-title-link" itemprop="url">外边距合并</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2021-10-20 22:32:22" itemprop="dateCreated datePublished" datetime="2021-10-20T22:32:22+08:00">2021-10-20</time>
    </span>
      <span class="post-meta-item">
        <span class="post-meta-item-icon">
          <i class="far fa-calendar-check"></i>
        </span>
        <span class="post-meta-item-text">更新于</span>
        <time title="修改时间：2023-06-25 16:57:29" itemprop="dateModified" datetime="2023-06-25T16:57:29+08:00">2023-06-25</time>
      </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/CSS/" itemprop="url" rel="index"><span itemprop="name">CSS</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h1 id="外边距合并问题"><a href="#外边距合并问题" class="headerlink" title="外边距合并问题"></a>外边距合并问题</h1><h2 id="首先，什么是外边距合并"><a href="#首先，什么是外边距合并" class="headerlink" title="首先，什么是外边距合并"></a>首先，什么是外边距合并</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">https://www.w3school.com.cn/css/css_margin_collapse.asp</span><br><span class="line">https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing</span><br><span class="line">https://www.w3.org/TR/CSS2/box.html#collapsing-margins</span><br></pre></td></tr></table></figure>



<p><strong>外边距合并指的是，当两个垂直外边距相遇时，它们将形成一个外边距。</strong></p>
<p><strong>合并后的外边距的高度等于两个发生合并的外边距的高度中的较大者。</strong></p>
<p>简单来说，这个的效果就是，两个外边距并不是进行的相加的边距，而是取了其中的最大值</p>
<p>一个简单的例子</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html lang=&quot;en&quot;&gt;</span><br><span class="line">&lt;head&gt;</span><br><span class="line">  &lt;meta charset=&quot;UTF-8&quot;&gt;</span><br><span class="line">  &lt;title&gt;Title&lt;/title&gt;</span><br><span class="line">  &lt;style&gt;</span><br><span class="line">    * &#123;</span><br><span class="line">      margin: 0;</span><br><span class="line">      padding: 0;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    .f &#123;</span><br><span class="line">      height: 400px;</span><br><span class="line">      width: 800px;</span><br><span class="line">      background-color: red;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    .c &#123;</span><br><span class="line">      height: 50%;</span><br><span class="line">      width: 50%;</span><br><span class="line">      background-color: blue;</span><br><span class="line">      margin-top: 25%;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">  &lt;/style&gt;</span><br><span class="line"></span><br><span class="line">&lt;/head&gt;</span><br><span class="line">&lt;body&gt;</span><br><span class="line">&lt;div class=&quot;f&quot;&gt;</span><br><span class="line">  &lt;div class=&quot;c&quot;&gt;&lt;/div&gt;</span><br><span class="line">&lt;/div&gt;</span><br><span class="line">&lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure>

<p>实际的效果</p>
<img src="/.io//image-20211020224217218.png" alt="image-20211020224217218" style="zoom:50%;">

<p>预想的效果</p>
<img src="/.io//image-20211020224237425.png" alt="image-20211020224237425" style="zoom:50%;">



<h2 id="有几种情况会产生外边距合并"><a href="#有几种情况会产生外边距合并" class="headerlink" title="有几种情况会产生外边距合并"></a>有几种情况会产生外边距合并</h2><h3 id="同一层相邻元素之间"><a href="#同一层相邻元素之间" class="headerlink" title="同一层相邻元素之间"></a><strong>同一层相邻元素之间</strong></h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">相邻的两个元素之间的外边距重叠，除非后一个元素加上clear-fix清除浮动。</span><br></pre></td></tr></table></figure>

<p>​    相邻元素， 元素包含了，<code>块级元素</code>，<code>行内元素</code>，<code>行内块元素</code></p>
<p>但是对于 <code>行内元素</code>来说，不能使用margin-top，来进行扩张。</p>
<p>对于 <code>行内块元素</code>  来说，因为他造成了 BFC，所以，margin-top，没有了合并的效果。</p>
<p>所以，最后还是使用了块级元素。</p>
<h3 id="没有内容将父元素和后代元素分开"><a href="#没有内容将父元素和后代元素分开" class="headerlink" title="没有内容将父元素和后代元素分开"></a><strong>没有内容将父元素和后代元素分开</strong></h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">原话：</span><br><span class="line">	如果没有边框border，内边距padding，行内内容，也没有创建块级格式上下文或清除浮动来分开一个块级元素的上边界margin-top 与其内一个或多个后代块级元素的上边界margin-top；或没有边框，内边距，行内内容，高度height，最小高度min-height或 最大高度max-height 来分开一个块级元素的下边界margin-bottom与其内的一个或多个后代后代块元素的下边界margin-bottom，则就会出现父块元素和其内后代块元素外边界重叠，重叠部分最终会溢出到父级块元素外面。</span><br></pre></td></tr></table></figure>

<p>这里的内容，包括了</p>
<p><strong>第一部分：</strong></p>
<p>​    <strong>边框：</strong>border    父元素使用，子元素使用并不会有效果。</p>
<p>​    同理，<strong>内边距：</strong>padding，也是一样的。</p>
<p>​    <strong>创建块级格式上下文：</strong>（BFC）我们后面再说：</p>
<p>​    现在我就直接贴上　MDN　的 url</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://developer.mozilla.org/zh-CN/docs/Web/Guide/CSS/Block_formatting_context</span><br></pre></td></tr></table></figure>

<p>​    <strong>清除浮动：</strong>不知道是要进行什么操作的意思。不知道是不是对子元素进行一次浮动，然后再在父元素上进行清除浮动。</p>
<p><strong>第二部分：</strong></p>
<p>​    父元素没有定义高度，所以最终高度会由子元素进行定义，因此，对于 <code>margin-bottom</code> 下边界会造成合并的效果。，然后重叠部分会溢出到父元素的外面。</p>
<h3 id="空的块级元素"><a href="#空的块级元素" class="headerlink" title="空的块级元素"></a><strong>空的块级元素</strong></h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">当一个块元素上边界margin-top 直接贴到元素下边界margin-bottom时也会发生边界折叠。这种情况会发生在一个块元素完全没有设定边框border、内边距padding、高度height、最小高度min-height 、最大高度max-height 、内容设定为inline或是加上clear-fix的时候。</span><br></pre></td></tr></table></figure>

<p>简单来说，就是一个空的块级元素</p>
<p>然后对其进行 上边距和下边距的 设置，最终的结果不会是两个相加，</p>
<p>而是选择最大的。</p>
<p>前提就是父元素不能设置</p>
<p>​    border，padding，height，min-height， max-height， display：inline， 和 加上 clear-fix。</p>
<p>对于最后一个clear-fix，有点没有理解清除，其他的还好， display：inline，就是设置成一个行内元素，因为是行内元素，所以外边距就没有效果了。其他的 border，padding，就是一些正常的解决合并问题的方法。</p>
<p>对于空的块级元素，连续相邻的外边距也是会合并的。</p>
<img src="/.io//image-20211021103824947.png" alt="image-20211021103824947" style="zoom:50%;">



<h3 id="注意："><a href="#注意：" class="headerlink" title="注意："></a>注意：</h3><ul>
<li>一些情况的组合会产生更多复杂的外边距离收起。</li>
<li>即使某些外边距为0，这些规则仍然适用。因此，父母元素的外边距是0，或最后一个外边距可能会“接触到第一个元素”到父母元素的外面。</li>
<li>如果参与折叠的外边距中包含的负值，折叠后的外边距的值为最大的正边距和最大的负边距（即绝对值的最大负边距）和；如果有—— 13px 8px 100px 一叠，远景的技术就是100px -13px的87px。（有负有正，取最大最小相加）</li>
<li>如果所有参与的户外边距都为负，折叠后的外边距的最大负边距值为多少。这个规则适用于户外元素和元素。 （全为负，取绝对值最大的。）</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">个人认为：</span><br><span class="line">	这样正负的判断，在修改边距的时候，有一个逐渐的过程，而不会出现突变情况。</span><br></pre></td></tr></table></figure>



<h2 id="解决外边距合并的办法"><a href="#解决外边距合并的办法" class="headerlink" title="解决外边距合并的办法"></a>解决外边距合并的办法</h2><p>首先一点：</p>
<p>​    <strong>只有普通文档流中块框的垂直外边距才会发生外边距合并。行内框、浮动框或绝对定位之间的外边距不会合并。</strong></p>
<p>行内块不会合并的原因是，他形成了BFC，块格式化上下文。</p>
<p>其他两个是因为他们脱离了普通文档流。</p>
<h3 id="解决兄弟元素的上下外边距合并"><a href="#解决兄弟元素的上下外边距合并" class="headerlink" title="解决兄弟元素的上下外边距合并"></a>解决兄弟元素的上下外边距合并</h3><h4 id="浮动"><a href="#浮动" class="headerlink" title="浮动"></a>浮动</h4><p>虽然浮动可以解决，但是因为是兄弟元素的外边距合并，有时会产生更多的问题。</p>
<h3 id="行内块"><a href="#行内块" class="headerlink" title="行内块"></a>行内块</h3><p>行内块 display: inline-block;    感觉比上面的好处多了很多。</p>
<h3 id="使用绝对定位"><a href="#使用绝对定位" class="headerlink" title="使用绝对定位"></a>使用绝对定位</h3><p>​        在这里我知道了一个小知识点，一般对绝对定位的时候都会直接加上 left，top，如果不加的话，那么就会相对于原来的位置不变。虽然也脱离了文档流，不占据的位置，但是从视觉上来说，他是解决了外边框合并的问题。</p>
<p>​    但是如果父元素没有给定高度的话，那么将不会把这个高度计算在内。</p>
<h3 id="对于父子元素的外边距合并"><a href="#对于父子元素的外边距合并" class="headerlink" title="对于父子元素的外边距合并"></a>对于父子元素的外边距合并</h3><h4 id="设置边框或内边距"><a href="#设置边框或内边距" class="headerlink" title="设置边框或内边距"></a>设置边框或内边距</h4><p>避免父子的外边距相邻</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">给父元素加上 border: 1px solid transparent;</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">padding: 1px;</span><br></pre></td></tr></table></figure>



<h4 id="设置浮动，绝对定位，行内块布局，和overflow"><a href="#设置浮动，绝对定位，行内块布局，和overflow" class="headerlink" title="设置浮动，绝对定位，行内块布局，和overflow"></a>设置浮动，绝对定位，行内块布局，和overflow</h4><p>这种的实现就是进行 BFC 块级格式化。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">float: left;</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">position: absolute;</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">display: inline-block;</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">overflow: hidden;</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">overflow: auto;</span><br></pre></td></tr></table></figure>



<h3 id="对于空的块级元素"><a href="#对于空的块级元素" class="headerlink" title="对于空的块级元素"></a>对于空的块级元素</h3><h4 id="设置边框，边距，高度"><a href="#设置边框，边距，高度" class="headerlink" title="设置边框，边距，高度"></a>设置边框，边距，高度</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">border: 1px solid transparent;</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">padding: 1px;</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">height: 1px;</span><br></pre></td></tr></table></figure>

<h4 id="块环境上下文"><a href="#块环境上下文" class="headerlink" title="块环境上下文"></a>块环境上下文</h4><p>比如 </p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">display: inline-block;</span><br><span class="line">overflow: hidden;</span><br></pre></td></tr></table></figure>


      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="http://tallgy.gitee.io/2021/10/20/JavaScript/%E6%96%B9%E6%B3%95/eval%E5%87%BD%E6%95%B0/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="tallgy">
      <meta itemprop="description" content="只是一个知识的搬运工">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="tallgy's blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2021/10/20/JavaScript/%E6%96%B9%E6%B3%95/eval%E5%87%BD%E6%95%B0/" class="post-title-link" itemprop="url">eval函数</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2021-10-20 11:01:49" itemprop="dateCreated datePublished" datetime="2021-10-20T11:01:49+08:00">2021-10-20</time>
    </span>
      <span class="post-meta-item">
        <span class="post-meta-item-icon">
          <i class="far fa-calendar-check"></i>
        </span>
        <span class="post-meta-item-text">更新于</span>
        <time title="修改时间：2023-06-25 16:57:29" itemprop="dateModified" datetime="2023-06-25T16:57:29+08:00">2023-06-25</time>
      </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/JavaScript/" itemprop="url" rel="index"><span itemprop="name">JavaScript</span></a>
        </span>
          ，
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/JavaScript/Global-Objects/" itemprop="url" rel="index"><span itemprop="name">Global_Objects</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h1 id="eval函数"><a href="#eval函数" class="headerlink" title="eval函数"></a>eval函数</h1><p><strong>文档</strong></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/eval</span><br></pre></td></tr></table></figure>



<p>这里学习使用eval函数的原因是, 前几天遇到一个问题是拷贝函数, </p>
<p>所以我就想说,先使用tostring, 然后再使用eval转为函数返回进行使用, 这样就进行了一次函数的复制.</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">let f = eval(`</span><br><span class="line">function fn() &#123;</span><br><span class="line">  console.log(1);</span><br><span class="line">  return 2;</span><br><span class="line">&#125;</span><br><span class="line">`);</span><br><span class="line"></span><br><span class="line">console.log(f);</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">你会发现结果 是不如人意的?我的想法就是这个字符串方法会被转义为一个函数赋值给f.但是却什么都没有,函数没有执行,并且没有返回值.</span><br><span class="line"></span><br><span class="line">undefined</span><br></pre></td></tr></table></figure>

<p>然后转念一想.可能是因为虽然转义为函数了,但是没有执行和返回.他只是定义了一下函数而已.</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">let f = eval(`</span><br><span class="line">function fn () &#123;</span><br><span class="line">  console.log(1);</span><br><span class="line">  return 2;</span><br><span class="line">&#125;;</span><br><span class="line">`);</span><br><span class="line"></span><br><span class="line">fn();</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">结果真的有输出.所以这样一想.我可以在内部加上一个立即执行函数啊</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">function fn () &#123;</span><br><span class="line">  console.log(1);</span><br><span class="line">  return 2;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">//我这里只是定义立即执行函数,但是没有执行.只需要使用 f(), 便可以进行函数调用了.</span><br><span class="line">let f = eval(`</span><br><span class="line">  ($&#123;fn.toString()&#125;)</span><br><span class="line">`);</span><br><span class="line"></span><br><span class="line">console.log(f.toString());</span><br><span class="line">console.log(f());</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">执行结果:</span><br><span class="line">function fn () &#123;</span><br><span class="line">  console.log(1);</span><br><span class="line">  return 2;</span><br><span class="line">&#125;</span><br><span class="line">1</span><br><span class="line">2</span><br></pre></td></tr></table></figure>


      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="http://tallgy.gitee.io/2021/10/19/JavaScript/%E5%AF%B9%E8%B1%A1/JavaScript%E6%B5%85%E6%8B%B7%E8%B4%9D%E5%92%8C%E6%B7%B1%E6%8B%B7%E8%B4%9D/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="tallgy">
      <meta itemprop="description" content="只是一个知识的搬运工">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="tallgy's blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2021/10/19/JavaScript/%E5%AF%B9%E8%B1%A1/JavaScript%E6%B5%85%E6%8B%B7%E8%B4%9D%E5%92%8C%E6%B7%B1%E6%8B%B7%E8%B4%9D/" class="post-title-link" itemprop="url">JavaScript浅拷贝和深拷贝</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2021-10-19 15:28:12" itemprop="dateCreated datePublished" datetime="2021-10-19T15:28:12+08:00">2021-10-19</time>
    </span>
      <span class="post-meta-item">
        <span class="post-meta-item-icon">
          <i class="far fa-calendar-check"></i>
        </span>
        <span class="post-meta-item-text">更新于</span>
        <time title="修改时间：2023-06-25 16:57:29" itemprop="dateModified" datetime="2023-06-25T16:57:29+08:00">2023-06-25</time>
      </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/JavaScript/" itemprop="url" rel="index"><span itemprop="name">JavaScript</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h1 id="浅拷贝"><a href="#浅拷贝" class="headerlink" title="浅拷贝"></a>浅拷贝</h1><p>很简单，就是只拷贝一层，不拷贝多层，因为对于引用数据类型，</p>
<p>他的数据是存放在堆中的，我们只是在栈中存放了他的地址。所以浅拷贝的问题就是对于引用数据类型还是没有进行拷贝。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">一个简单的demo</span><br><span class="line"></span><br><span class="line">这里，有两个循环操作。对于forin，他会循着原型链向上查找，</span><br><span class="line">而对于 Object.keys() 和 Object.getOwnPropertyNames()，他只会返回属于自身的属性。</span><br><span class="line">而不会向上寻找原型链</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">let obj1 = &#123;</span><br><span class="line">  a: 1</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">let obj2 = &#123;</span><br><span class="line">  b: 2</span><br><span class="line">&#125;;</span><br><span class="line">obj2.__proto__ = obj1;</span><br><span class="line"></span><br><span class="line">for (const obj2Key in obj2) &#123;</span><br><span class="line">  console.log(obj2Key);</span><br><span class="line">&#125;</span><br><span class="line">console.log(Object.keys(obj2))</span><br><span class="line">console.log(Object.getOwnPropertyNames(obj2))</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">b</span><br><span class="line">a</span><br><span class="line"></span><br><span class="line">[ &#x27;b&#x27; ]</span><br><span class="line"></span><br><span class="line">[ &#x27;b&#x27; ]</span><br></pre></td></tr></table></figure>



<p>所以我们考虑到是否要将原型链上的一起拷贝之后，再进行拷贝</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">keys代表了要拷贝的key</span><br><span class="line"></span><br><span class="line">const obj = &#123;&#125;</span><br><span class="line"></span><br><span class="line">for (const key in keys) &#123;</span><br><span class="line">  obj[keys[key]] = obj2[keys[key]];</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这个就是浅拷贝了。比较简单</p>
<h2 id="同时也可以使用-Object-assign-进行浅拷贝"><a href="#同时也可以使用-Object-assign-进行浅拷贝" class="headerlink" title="同时也可以使用 Object.assign() 进行浅拷贝"></a>同时也可以使用 <code>Object.assign()</code> 进行浅拷贝</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/assign</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Object.assign(target, source);</span><br><span class="line"></span><br><span class="line">第一个参数是目标对象, 第二个参数是源对象,</span><br><span class="line">我们会将源对象的值拷贝给目标对象,对于重复的会被覆盖.</span><br><span class="line">然后再将目标对象返回.</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">const target = &#123; a: 1, b: 2 &#125;;</span><br><span class="line">const source = &#123; b: 4, c: 5, x: &#123;</span><br><span class="line">    a: 1</span><br><span class="line">  &#125; &#125;;</span><br><span class="line"></span><br><span class="line">const returnedTarget = Object.assign(target, source);</span><br><span class="line"></span><br><span class="line">console.log(target);</span><br><span class="line">// expected output: Object &#123; a: 1, b: 4, c: 5, x: &#123; a: 1 &#125; &#125;</span><br><span class="line">console.log(returnedTarget);</span><br><span class="line">// expected output: Object &#123; a: 1, b: 4, c: 5, x: &#123; a: 1 &#125; &#125;</span><br><span class="line"></span><br><span class="line">source.x.a = 3;</span><br><span class="line">console.log(target);</span><br><span class="line">// expected output: Object &#123; a: 1, b: 4, c: 5, x: &#123; a: 3 &#125; &#125;</span><br><span class="line">console.log(returnedTarget);</span><br><span class="line">// expected output: Object &#123; a: 1, b: 4, c: 5, x: &#123; a: 3 &#125; &#125;</span><br></pre></td></tr></table></figure>



<h1 id="深拷贝"><a href="#深拷贝" class="headerlink" title="深拷贝"></a>深拷贝</h1><p>和浅拷贝不同的是，深拷贝，是要进行递归，吧对象里面的对象也要拷贝出来。</p>
<h2 id="第一种：使用-JSON的方法，这个方法我也觉得很巧妙，"><a href="#第一种：使用-JSON的方法，这个方法我也觉得很巧妙，" class="headerlink" title="第一种：使用 JSON的方法，这个方法我也觉得很巧妙，"></a>第一种：使用 JSON的方法，这个方法我也觉得很巧妙，</h2><p>除了不能拷贝 function，正则，Symbol之外，其他都很不错。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">方法也很简单</span><br><span class="line"></span><br><span class="line">先对其进行string化，然后再json化，所以简单的使用没有问题。</span><br><span class="line">JSON.parse(JSON.stringify(obj))</span><br></pre></td></tr></table></figure>



<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">let obj = &#123;</span><br><span class="line">  reg : /^aaa$/,</span><br><span class="line">  fun: function()&#123; console.log(1) &#125;,</span><br><span class="line">  syb:Symbol(&#x27;foo&#x27;),</span><br><span class="line">  aa:&#x27;aa&#x27;</span><br><span class="line">&#125;;</span><br><span class="line">let cp = JSON.parse(JSON.stringify(obj));</span><br><span class="line">console.log(cp);</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123; reg: &#123;&#125;, aa: &#x27;aa&#x27; &#125;</span><br></pre></td></tr></table></figure>



<h2 id="第二种，就是简单的类型判断加递归了"><a href="#第二种，就是简单的类型判断加递归了" class="headerlink" title="第二种，就是简单的类型判断加递归了"></a>第二种，就是简单的类型判断加递归了</h2><p>就判断是否为基本数据类型，如果是那么就进行复制，如果不是那么就进入递归</p>
<p>其中，对于正则，基本数据类型，可以直接赋值。</p>
<p>对于对象，使用递归，</p>
<p>对于函数，我这里下面再讲</p>
<h4 id="类型判断"><a href="#类型判断" class="headerlink" title="类型判断"></a>类型判断</h4><p>这里，先用<code>typeof</code>判断是否为 <code>object</code>，</p>
<p>然后，对于object，存在 null，对象，数组，正则和使用new进行创建的基本数据类型</p>
<p>​    在这里，我把使用new方法创建的基本数据类型也算为基本数据类型。</p>
<p>对于非object，有function，和基本数据类型。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">function getType(target) &#123;</span><br><span class="line"></span><br><span class="line">  const type = typeof target;</span><br><span class="line">  if (type == &#x27;object&#x27;) &#123;</span><br><span class="line">    if (target === null) &#123;</span><br><span class="line">      // 空</span><br><span class="line">      return &#x27;null&#x27;;</span><br><span class="line">    &#125; else if (Array.isArray(target)) &#123;</span><br><span class="line">      // 数组</span><br><span class="line">      return &#x27;array&#x27;;</span><br><span class="line">    &#125; else if (target.constructor === RegExp) &#123;</span><br><span class="line">      //正则</span><br><span class="line">      return &#x27;regexp&#x27;</span><br><span class="line">    &#125; else &#123;</span><br><span class="line">      // 对象，这里还要判断是否为map和set对象。</span><br><span class="line">      //并且，map，set只能使用 forof 进行循环，或者使用自带的 oreach 进行循环。</span><br><span class="line">      if (typeof target.valueOf() === &#x27;object&#x27;) &#123;</span><br><span class="line">        return &#x27;object&#x27;;</span><br><span class="line">      &#125; else &#123;</span><br><span class="line">        return &#x27;basic&#x27;;</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125; else if (type == &#x27;function&#x27;) &#123;</span><br><span class="line">    return &#x27;function&#x27;;</span><br><span class="line">  &#125; else &#123;</span><br><span class="line">    return &#x27;basic&#x27;;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">这里也可以使用 Object.prototype.toString.call(); 方法进行调用来判断是什么类型的.这个就比较方便,直接可以将map,set,对象,数组,基本数据类型等都辨别出来.</span><br><span class="line">可以看看我写的另一个关于 类型判断的blog ,里面有.</span><br></pre></td></tr></table></figure>



<h4 id="然后就是递归"><a href="#然后就是递归" class="headerlink" title="然后就是递归"></a>然后就是递归</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">function deepClone(target) &#123;</span><br><span class="line">  let result;</span><br><span class="line"></span><br><span class="line">  for (const key in target) &#123;</span><br><span class="line">    result[key] = recursion(target[key]);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  return result;</span><br><span class="line">  </span><br><span class="line">  function recursion(target) &#123;</span><br><span class="line">    if (&#x27;基本数据类型&#x27;) &#123;</span><br><span class="line">      return target;</span><br><span class="line">    &#125; else if (&#x27;函数&#x27;) &#123;</span><br><span class="line">		</span><br><span class="line">    &#125; else &#123;</span><br><span class="line">      //对象</span><br><span class="line">      return recursion(target)</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h4 id="对于函数如何进行拷贝"><a href="#对于函数如何进行拷贝" class="headerlink" title="对于函数如何进行拷贝"></a>对于函数如何进行拷贝</h4><p>前几天面试问到了..</p>
<p>我的想法，有三种方式，</p>
<p>​    <strong>第一种：使用toString，然后再使用eval。</strong>    </p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">let fn = function () &#123;</span><br><span class="line">  console.log(1);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">function fn1() &#123;</span><br><span class="line">  console.log(1)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">这里我对于eval函数的使用还是不够了解。</span><br><span class="line">这里，我不知道为什么， eval(fn.toString()) 没有返回值，所以我写了一个箭头函数字符串进行包装和执行。</span><br><span class="line">	这里，需要使用一个箭头函数进行包装，如果使用普通函数进行包装。也没有用处。</span><br><span class="line">let fn2 = eval(&#x27;() =&gt; &#x27; + fn1.toString())(); //这里，fn和fn1都可以运行。</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">这样写也可以。</span><br><span class="line">eval(`</span><br><span class="line">  (() =&gt; fn)()</span><br><span class="line">`)()</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">应该是因为需要使用()进行包裹.</span><br><span class="line">let a = eval(`</span><br><span class="line">  (function fn() &#123;</span><br><span class="line">    console.log(1);</span><br><span class="line">    return 1;</span><br><span class="line">  &#125;)</span><br><span class="line">`);</span><br><span class="line">a()</span><br><span class="line">console.log(a.toString())</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">1</span><br><span class="line">function fn() &#123;</span><br><span class="line">    console.log(1);</span><br><span class="line">    return 1;</span><br><span class="line">  &#125;</span><br></pre></td></tr></table></figure>

<p>​    </p>
<p><strong>第二种：使用new Function(‘return ‘ + func.toString())();</strong></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">let f = new Function(&#x27;return &#x27; + fn.toString())()</span><br><span class="line"></span><br><span class="line">f();</span><br></pre></td></tr></table></figure>

<p>​    <strong>第三种：使用bind函数进行一次绑定。但是这个对于有传参的函数会有所不同。</strong></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">这个有个要求，因为bind函数实则就是对于一个函数进行了call方法，但是是一个延迟的调用。</span><br><span class="line"></span><br><span class="line">从一个简单的逻辑来说，应该是并没有进行一个从底层复制操作的。因为是直接进行的 简单赋值。</span><br><span class="line"></span><br><span class="line">let f = fn.bind()</span><br><span class="line">f();</span><br></pre></td></tr></table></figure>


      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="http://tallgy.gitee.io/2021/10/19/%E9%9A%8F%E7%AC%94/Git%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="tallgy">
      <meta itemprop="description" content="只是一个知识的搬运工">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="tallgy's blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2021/10/19/%E9%9A%8F%E7%AC%94/Git%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4/" class="post-title-link" itemprop="url">Git常用命令</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2021-10-19 14:10:15" itemprop="dateCreated datePublished" datetime="2021-10-19T14:10:15+08:00">2021-10-19</time>
    </span>
      <span class="post-meta-item">
        <span class="post-meta-item-icon">
          <i class="far fa-calendar-check"></i>
        </span>
        <span class="post-meta-item-text">更新于</span>
        <time title="修改时间：2023-06-25 16:57:29" itemprop="dateModified" datetime="2023-06-25T16:57:29+08:00">2023-06-25</time>
      </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/%E9%9A%8F%E7%AC%94/" itemprop="url" rel="index"><span itemprop="name">随笔</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h1 id="Git常用命令"><a href="#Git常用命令" class="headerlink" title="Git常用命令"></a>Git常用命令</h1><p>新建一个git仓库</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git init</span><br></pre></td></tr></table></figure>



<p>将内容进行本地提交</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git add .</span><br></pre></td></tr></table></figure>



<p>设置提交到GitHub的url</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git remote add origin https://xxx</span><br></pre></td></tr></table></figure>



<p>提交</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git push -u origin master</span><br></pre></td></tr></table></figure>



<p>拉取</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git pull origin master</span><br></pre></td></tr></table></figure>



<p>同时将一个项目提交到两个仓库</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">需要再添加一个新的仓库</span><br><span class="line">git remote set-url --add origin https://xx</span><br></pre></td></tr></table></figure>

<p>也可以在配置文件里面进行修改</p>
<p>.git/config</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">在文件里面的[remote &quot;origin&quot;]</span><br><span class="line">下面添加一个url：设置为自己的另一个仓库的url地址就可以在提交的时候将仓库提交到远程了</span><br></pre></td></tr></table></figure>


      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="http://tallgy.gitee.io/2021/10/19/JavaScript/%E9%9A%8F%E7%AC%94/JavaScript%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="tallgy">
      <meta itemprop="description" content="只是一个知识的搬运工">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="tallgy's blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2021/10/19/JavaScript/%E9%9A%8F%E7%AC%94/JavaScript%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2/" class="post-title-link" itemprop="url">JavaScript类型转换</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2021-10-19 10:07:37" itemprop="dateCreated datePublished" datetime="2021-10-19T10:07:37+08:00">2021-10-19</time>
    </span>
      <span class="post-meta-item">
        <span class="post-meta-item-icon">
          <i class="far fa-calendar-check"></i>
        </span>
        <span class="post-meta-item-text">更新于</span>
        <time title="修改时间：2023-06-25 16:57:29" itemprop="dateModified" datetime="2023-06-25T16:57:29+08:00">2023-06-25</time>
      </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/JavaScript/" itemprop="url" rel="index"><span itemprop="name">JavaScript</span></a>
        </span>
          ，
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/JavaScript/Global-Objects/" itemprop="url" rel="index"><span itemprop="name">Global_Objects</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h1 id="JavaScript类型转换"><a href="#JavaScript类型转换" class="headerlink" title="JavaScript类型转换"></a>JavaScript类型转换</h1><p>参考的文章</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">https://www.cnblogs.com/shikaka/p/10463293.html</span><br><span class="line">https://www.cnblogs.com/shikaka/p/10473462.html</span><br></pre></td></tr></table></figure>



<h2 id="基本数据类型"><a href="#基本数据类型" class="headerlink" title="基本数据类型"></a>基本数据类型</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">string， number， Boolean， null， undefined， symbol</span><br></pre></td></tr></table></figure>

<p>基本数据类型是没有方法可以调用的。</p>
<p>但是我们却发现，</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#x27;aaa&#x27;.indexOf(&#x27;a&#x27;);</span><br></pre></td></tr></table></figure>

<p>这个明明是基本数据类型，但是却可以调用方法，这个是为什么呢。</p>
<p>这个是因为<code>JavaScript</code>在底层进行了一个操作，当发现调用方法的是一个基本数据类型的话，会根据这个类型来创建一个对应的引用数据类型对象。然后再调用这个方法，调用之后将返回值进行返回并将这个对象进行删除。</p>
<p>在 <code>JavaScript</code> 中，类型转换主要的两个方法是</p>
<p><code>valueOf</code> ， <code>toString</code></p>
<p>我们下面分别对这两个进行一个判断使用操作。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">let a = 1,</span><br><span class="line">    b = &#x27;a&#x27;,</span><br><span class="line">    c = true,</span><br><span class="line">    d = undefined,</span><br><span class="line">    e = null,</span><br><span class="line">    f = [1, 2, 3],</span><br><span class="line">    g = [&#x27;1&#x27;, &#x27;3&#x27;],</span><br><span class="line">    h = new Number(3),</span><br><span class="line">    i = new String(&#x27;12&#x27;),</span><br><span class="line">    j = new Boolean(false),</span><br><span class="line">    k = new Object(&#123; a: 3&#125; ),</span><br><span class="line">    l = &#123; b: 4 &#125;,</span><br><span class="line">    m = function () &#123;&#125;,</span><br><span class="line">    n = new Date(),</span><br><span class="line">    o = new RegExp(&#x27;sss&#x27;),</span><br><span class="line">    p = /sss/,</span><br><span class="line">    q = `sdcard`,</span><br><span class="line">    r = new Array([1,2,3]);</span><br></pre></td></tr></table></figure>



<h2 id="valueOf-NaN"><a href="#valueOf-NaN" class="headerlink" title="valueOf"></a>valueOf</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">console.log(a.valueOf());</span><br><span class="line">console.log(b.valueOf());</span><br><span class="line">console.log(c.valueOf());</span><br><span class="line">// console.log(d.valueOf());</span><br><span class="line">// console.log(e.valueOf());</span><br><span class="line">console.log(f.valueOf());</span><br><span class="line">console.log(h.valueOf());</span><br><span class="line">console.log(i.valueOf());</span><br><span class="line">console.log(j.valueOf());</span><br><span class="line">console.log(k.valueOf());</span><br><span class="line">console.log(n.valueOf());</span><br><span class="line">console.log(o.valueOf());</span><br></pre></td></tr></table></figure>

<h4 id="这就是执行的结果。"><a href="#这就是执行的结果。" class="headerlink" title="这就是执行的结果。"></a>这就是执行的结果。</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">1</span><br><span class="line">a</span><br><span class="line">true</span><br><span class="line">[ 1, 2, 3 ]</span><br><span class="line">3</span><br><span class="line">12</span><br><span class="line">false</span><br><span class="line">&#123; a: 3 &#125;</span><br><span class="line">1634610286344</span><br><span class="line">/sss/</span><br></pre></td></tr></table></figure>

<h4 id="我们可以从结果里面看到"><a href="#我们可以从结果里面看到" class="headerlink" title="我们可以从结果里面看到"></a>我们可以从结果里面看到</h4><table>
<thead>
<tr>
<th>类型</th>
<th>结果</th>
</tr>
</thead>
<tbody><tr>
<td>null，undefined</td>
<td>没有valueOf方法，会报错</td>
</tr>
<tr>
<td>基本数据类型，包括Symbol类型</td>
<td>valueOf方法为其本身，可以使用 === 来判断，Symbol为true。</td>
</tr>
<tr>
<td>对象，数组，方法，正则</td>
<td>也为其本身</td>
</tr>
<tr>
<td>使用new方法创建的基本数据类型，new number(1)</td>
<td>为其值，与原来不等。</td>
</tr>
<tr>
<td>date类型</td>
<td>当前时间距 1970.01.01 午夜的毫秒数</td>
</tr>
</tbody></table>
<p>所以我们可以看到，</p>
<p>基本除了对象，其他的类型使用valueOf方法都可以转换成基本数据类型。</p>
<p>对于使用new方法创建的基本数据类型的引用数据类型，也会被转换成基本数据类型。</p>
<p>这里的原因，是因为 <code>number </code>对象对 <code>valueOf</code> 进行了一次重写，所以在调用的时候就会调用自己所重写的方法，于是返回的结果会不同。其他也同理。</p>
<p>但是<code>JavaScript</code>内部是如何进行操作，取出值的，我还是不了解。</p>
<h2 id="toString-NaN"><a href="#toString-NaN" class="headerlink" title="toString"></a>toString</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">console.log(a.toString());</span><br><span class="line">console.log(b.toString());</span><br><span class="line">console.log(c.toString());</span><br><span class="line">// console.log(d.toString());</span><br><span class="line">// console.log(e.toString());</span><br><span class="line">console.log(f.toString());</span><br><span class="line">console.log(h.toString());</span><br><span class="line">console.log(i.toString());</span><br><span class="line">console.log(j.toString());</span><br><span class="line">console.log(k.toString());</span><br><span class="line">console.log(n.toString());</span><br><span class="line">console.log(o.toString());</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">1</span><br><span class="line">a</span><br><span class="line">true</span><br><span class="line">1,2,3</span><br><span class="line">3</span><br><span class="line">12</span><br><span class="line">false</span><br><span class="line">[object Object]</span><br><span class="line">Tue Oct 19 2021 10:50:07 GMT+0800 (中国标准时间)</span><br><span class="line">/sss/</span><br></pre></td></tr></table></figure>



<table>
<thead>
<tr>
<th>类型</th>
<th>结果</th>
</tr>
</thead>
<tbody><tr>
<td>null， undefined</td>
<td>没有toString方法</td>
</tr>
<tr>
<td>基本数据类型</td>
<td>直接转为字符串</td>
</tr>
<tr>
<td>普通对象</td>
<td>直接转为字符串 [object Object]</td>
</tr>
<tr>
<td>日期，正则对象</td>
<td>转为对应值的字符串</td>
</tr>
</tbody></table>
<h1 id="隐式类型转换"><a href="#隐式类型转换" class="headerlink" title="隐式类型转换"></a>隐式类型转换</h1><p>我这里主要讲解一下隐式类型转换</p>
<h3 id="对于一个对象转为基本数据类型的方法"><a href="#对于一个对象转为基本数据类型的方法" class="headerlink" title="对于一个对象转为基本数据类型的方法"></a>对于一个对象转为基本数据类型的方法</h3><p>对于一个不是基本数据类型的。会先通过 <code>valueOf</code> 转换，看是否能转为基本数据类型</p>
<p>如果还不可以，然后就会使用 <code>toString </code>方法转为字符串。然后再来进行判断。</p>
<p>对于 <code>Date</code> 对象的话，使用顺序会反过来</p>
<h3 id="转字符串。"><a href="#转字符串。" class="headerlink" title="转字符串。"></a>转字符串。</h3><p>就直接toString方法就行了。</p>
<h3 id="转数字"><a href="#转数字" class="headerlink" title="转数字"></a>转数字</h3><p>就类似于 <code>Number(undefined); </code> 的情况</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">null， false		-&gt; 0</span><br><span class="line">undefined		-&gt; NaN</span><br></pre></td></tr></table></figure>

<h4 id="对于字符串"><a href="#对于字符串" class="headerlink" title="对于字符串"></a>对于字符串</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">字符串含有字符的。没有特殊含义的都为 NaN</span><br><span class="line"></span><br><span class="line">&#x27;1.111111111111111e+50&#x27; 这个就会转为数字，还有进制表示和小数点会转，其他带有字符会被转成 NaN</span><br></pre></td></tr></table></figure>

<h4 id="对于对象"><a href="#对于对象" class="headerlink" title="对于对象"></a>对于对象</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">先使用前面我说过的规则转为基本类型，然后再进行转换。</span><br></pre></td></tr></table></figure>



<h3 id="转布尔值"><a href="#转布尔值" class="headerlink" title="转布尔值"></a>转布尔值</h3><p>几个特殊值为 <code>false</code></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">NaN, undefined， null， 0， +0， -0， &#x27;&#x27;</span><br></pre></td></tr></table></figure>

<p>其他为true</p>
<h2 id="基本上涉及运算和比较就会出现隐式类型转换"><a href="#基本上涉及运算和比较就会出现隐式类型转换" class="headerlink" title="基本上涉及运算和比较就会出现隐式类型转换"></a>基本上涉及运算和比较就会出现隐式类型转换</h2><h3 id="加号"><a href="#加号" class="headerlink" title="加号 +"></a>加号 +</h3><p>存在字符串则转为字符串的拼接操作</p>
<p>非字符串就会转数字操作。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">console.log(1+2+&#x27;&#x27;)</span><br><span class="line">1+2 先为3，</span><br><span class="line">然后3+&#x27;&#x27; 为3</span><br></pre></td></tr></table></figure>

<p>这个就涉及到了上面的转换规则</p>
<p>这里有个小问题</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">let x = Symbol(1);</span><br><span class="line">console.log(x + &#x27;1&#x27;)</span><br><span class="line">这样会抛出异常，虽然Symbol可以使用toString，</span><br><span class="line">但是不能进行隐式转换。</span><br></pre></td></tr></table></figure>



<h3 id="减号-乘号-除号"><a href="#减号-乘号-除号" class="headerlink" title="减号 - 乘号 * 除号 /"></a>减号 - 乘号 * 除号 /</h3><p>会转为数字进行运算。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">特殊的，对于 NaN运算得NaN</span><br><span class="line">对于 0/0 等于 NaN</span><br><span class="line">对于 1/0 等于 Infinity</span><br></pre></td></tr></table></figure>



<p>|| 和 &amp;&amp; 这里这个返回值不是<code>true</code>和<code>false</code>而是返回两边操作数的执行结果。</p>
<h3 id="比较运算"><a href="#比较运算" class="headerlink" title="比较运算"></a>比较运算</h3><p><strong>转换规则</strong></p>
<img src="/.io//image-20211019105728109.png" alt="image-20211019105728109" style="zoom:67%;">



<h4 id="和"><a href="#和" class="headerlink" title="== 和 ==="></a>== 和 ===</h4><p>非严格相等等号 可以允许强制类型转换，</p>
<p>而严格相等等号 不允许强制类型的转换。</p>
<p>其他的就如上，使用上面的转换规则进行转换。</p>
<p>这里有个小问题点</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">if ([]) &#123;</span><br><span class="line">  console.log(1)</span><br><span class="line">&#125; else &#123;</span><br><span class="line">  console.log(2)</span><br><span class="line">&#125;</span><br><span class="line">此时会输出为1，所以说明了[]在if判断里面为真，但是 [] == true 为false，</span><br><span class="line">这里可以看上面 转布尔值 那个地方，说明了，布尔在进行判断时 除了 undefined，null，NaN，0， &#x27;&#x27;，其他都为true</span><br><span class="line">因此也可以说明，if判断是使用的 Boolean 来进行的判断为真还是为假。而不是与true进行的比较。</span><br></pre></td></tr></table></figure>



<h4 id="null和undefined的比较"><a href="#null和undefined的比较" class="headerlink" title="null和undefined的比较"></a>null和undefined的比较</h4><p>null和undefined进行比较时</p>
<p>​    使用非严格等号为 true</p>
<p>​    使用严格等号为 false</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">null == undefined</span><br></pre></td></tr></table></figure>



<h4 id="NaN-不与任何值相等，包括自己"><a href="#NaN-不与任何值相等，包括自己" class="headerlink" title="NaN 不与任何值相等，包括自己"></a>NaN 不与任何值相等，包括自己</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">NaN == NaN	false</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">并且 NaN &gt; 0 和 NaN &lt;= 0 都为 false</span><br></pre></td></tr></table></figure>






      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="http://tallgy.gitee.io/2021/10/18/JavaScript/%E6%96%B9%E6%B3%95/call-apply-bind%E5%AE%9E%E7%8E%B0/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="tallgy">
      <meta itemprop="description" content="只是一个知识的搬运工">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="tallgy's blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2021/10/18/JavaScript/%E6%96%B9%E6%B3%95/call-apply-bind%E5%AE%9E%E7%8E%B0/" class="post-title-link" itemprop="url">call,apply,bind实现</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2021-10-18 14:04:16" itemprop="dateCreated datePublished" datetime="2021-10-18T14:04:16+08:00">2021-10-18</time>
    </span>
      <span class="post-meta-item">
        <span class="post-meta-item-icon">
          <i class="far fa-calendar-check"></i>
        </span>
        <span class="post-meta-item-text">更新于</span>
        <time title="修改时间：2023-06-25 16:57:29" itemprop="dateModified" datetime="2023-06-25T16:57:29+08:00">2023-06-25</time>
      </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/JavaScript/" itemprop="url" rel="index"><span itemprop="name">JavaScript</span></a>
        </span>
          ，
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/JavaScript/Global-Objects/" itemprop="url" rel="index"><span itemprop="name">Global_Objects</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h1 id="call-apply-bind源码的实现"><a href="#call-apply-bind源码的实现" class="headerlink" title="call,apply,bind源码的实现"></a>call,apply,bind源码的实现</h1><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">相同点：都是替换 this 的指向</span><br><span class="line">区别：</span><br><span class="line">  call：第一个参数为this指向，后续的参数当作本身方法的传参</span><br><span class="line">  apply：第一个参数为this指向，第二参数为一个数组，数组内部为方法本身的传参</span><br><span class="line">  bind：整体同 call 方法一样，但是首先，bind不会马上执行方法，其次，bind方法返回的方法也可以携带参数继续向原方法添加。</span><br><span class="line"></span><br><span class="line">案例：</span><br><span class="line"></span><br><span class="line">const a = (a, b) =&gt; &#123;</span><br><span class="line">    console.log(a, b);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">// call</span><br><span class="line">a.call(&#123;&#125;, 1, 2);</span><br><span class="line"></span><br><span class="line">// apply</span><br><span class="line">a.apply(&#123;&#125;, [1, 2]);</span><br><span class="line"></span><br><span class="line">// bind</span><br><span class="line">const b = a.bind(&#123;&#125;, 1, 2);</span><br><span class="line">b();</span><br><span class="line"></span><br><span class="line">// OR</span><br><span class="line"></span><br><span class="line">const b = a.bind(&#123;&#125;, 1);</span><br><span class="line">b();</span><br><span class="line">b(2);</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h2 id="call方法"><a href="#call方法" class="headerlink" title="call方法"></a>call方法</h2><p>使用，就是替换了this的指向，传参使用的基本传参。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">这里将方法写在了Function函数的原型里面，这样因为通过原型链就可以找到这个方法了。</span><br><span class="line">Function.prototype.myCall = function (ctx) &#123;</span><br><span class="line">  ctx = ctx || window;</span><br><span class="line"></span><br><span class="line">  //这里这个this，指向的就是方法。这里使用Symbol，用于避免出现方法重复。</span><br><span class="line">  const fn = Symbol(&#x27;fn&#x27;);</span><br><span class="line">  ctx[fn] = this;</span><br><span class="line"></span><br><span class="line">  // 获取参数</span><br><span class="line">  const args = [...arguments].slice(1);</span><br><span class="line">  // 使用ctx来进行调用。替换了this指向。</span><br><span class="line">  const result = ctx[fn](...args);</span><br><span class="line"></span><br><span class="line">  delete ctx[fn];</span><br><span class="line">  return result;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>更新的写法</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">const call = (ctx, ...args) =&gt; &#123;</span><br><span class="line">    const fn = Symbol(&#x27;fn&#x27;);</span><br><span class="line"></span><br><span class="line">    ctx[fn] = this;</span><br><span class="line">    const res = ctx[fn](...args);</span><br><span class="line"></span><br><span class="line">    return res;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">fn.call(db, &#x27;cc&#x27;, 1);</span><br></pre></td></tr></table></figure>



<h2 id="apply方法"><a href="#apply方法" class="headerlink" title="apply方法"></a>apply方法</h2><p>同上，传参使用的是数组传参。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">Function.prototype.myApply = function (ctx, args) &#123;</span><br><span class="line">  ctx = ctx || window;</span><br><span class="line">  </span><br><span class="line">  const fn = Symbol(&#x27;fn&#x27;);</span><br><span class="line">  ctx[fn] = this;</span><br><span class="line">  </span><br><span class="line">  const result = ctx[fn](...args);</span><br><span class="line">  </span><br><span class="line">  delete ctx[fn];</span><br><span class="line">  return result;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>更新的写法</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">const apply = (ctx, args) =&gt; &#123;</span><br><span class="line">    const fn = Symbol(&#x27;fn&#x27;);</span><br><span class="line"></span><br><span class="line">    ctx[fn] = this;</span><br><span class="line">    const res = ctx[fn](...args);</span><br><span class="line"></span><br><span class="line">    return res;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">fn.apply(db, [&#x27;cc&#x27;, 1]);</span><br></pre></td></tr></table></figure>



<h2 id="bind方法"><a href="#bind方法" class="headerlink" title="bind方法"></a>bind方法</h2><p>同call方法的参数，但是不是马上执行，需要自己执行一次</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">Function.prototype.myBind = function (ctx) &#123;</span><br><span class="line">  ctx = ctx || window;</span><br><span class="line">  </span><br><span class="line">  const fn = Symbol(&#x27;fn&#x27;);</span><br><span class="line">  const args = [...arguments].slice(1);</span><br><span class="line">  </span><br><span class="line">  ctx[fn] = this;</span><br><span class="line">  </span><br><span class="line">  return () =&gt; &#123;</span><br><span class="line">    const result = ctx[fn](...args);</span><br><span class="line">    delete ctx[fn];</span><br><span class="line">    </span><br><span class="line">    return result;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>更新的写法</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">const bind = (ctx, ...args) =&gt; &#123;</span><br><span class="line">    const fn = Symbol(&#x27;fn&#x27;);</span><br><span class="line">    ctx[fn] = this;</span><br><span class="line"></span><br><span class="line">    return (...newArgs) =&gt; &#123;</span><br><span class="line">        const res = ctx[fn](...args, ...newArgs);</span><br><span class="line">        return res;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">fn.bind(db, &#x27;cc&#x27;, 1)();</span><br></pre></td></tr></table></figure>


      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="http://tallgy.gitee.io/2021/10/17/JavaScript/%E9%9A%8F%E7%AC%94/%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E5%88%A4%E6%96%AD/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="tallgy">
      <meta itemprop="description" content="只是一个知识的搬运工">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="tallgy's blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2021/10/17/JavaScript/%E9%9A%8F%E7%AC%94/%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E5%88%A4%E6%96%AD/" class="post-title-link" itemprop="url">数据类型判断</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2021-10-17 15:08:23" itemprop="dateCreated datePublished" datetime="2021-10-17T15:08:23+08:00">2021-10-17</time>
    </span>
      <span class="post-meta-item">
        <span class="post-meta-item-icon">
          <i class="far fa-calendar-check"></i>
        </span>
        <span class="post-meta-item-text">更新于</span>
        <time title="修改时间：2023-06-25 16:57:29" itemprop="dateModified" datetime="2023-06-25T16:57:29+08:00">2023-06-25</time>
      </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/JavaScript/" itemprop="url" rel="index"><span itemprop="name">JavaScript</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h1 id="JavaScript判断数据的类型的方法"><a href="#JavaScript判断数据的类型的方法" class="headerlink" title="JavaScript判断数据的类型的方法"></a>JavaScript判断数据的类型的方法</h1><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">let obj = &#123;</span><br><span class="line">  a: 1,</span><br><span class="line">  h: new Number(3),</span><br><span class="line"></span><br><span class="line">  b: &#x27;a&#x27;,</span><br><span class="line">  i: new String(&#x27;12&#x27;),</span><br><span class="line">  q: `sdcard`,</span><br><span class="line"></span><br><span class="line">  c: true,</span><br><span class="line">  j: new Boolean(false),</span><br><span class="line"></span><br><span class="line">  f: [1, 2, 3],</span><br><span class="line">  g: [&#x27;1&#x27;, &#x27;3&#x27;],</span><br><span class="line"></span><br><span class="line">  k: new Object(&#123; a: 3&#125; ),</span><br><span class="line">  l: &#123; b: 4 &#125;,</span><br><span class="line"></span><br><span class="line">  o: new RegExp(&#x27;sss&#x27;),</span><br><span class="line">  p: /sss/,</span><br><span class="line"></span><br><span class="line">  d: undefined,</span><br><span class="line">  e: null,</span><br><span class="line">  n: new Date(),</span><br><span class="line">  m: function () &#123;&#125;,</span><br><span class="line">  r: new Set([2, &#x27;1&#x27;, &#x27;aaa&#x27;]),</span><br><span class="line">  s: new Map([[&#x27;a&#x27;, 1], [2, &#x27;aa&#x27;], [&#x27;xxx&#x27;, 123]]),</span><br><span class="line">  t: Symbol(1),</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="typeof"><a href="#typeof" class="headerlink" title="typeof"></a>typeof</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/typeof</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">for (const k in obj) &#123;</span><br><span class="line">  console.log(&#x27; --  &#x27;);</span><br><span class="line">  console.log(obj[k]);</span><br><span class="line">  console.log(typeof obj[k]);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><span class="line"> --</span><br><span class="line">1</span><br><span class="line">number</span><br><span class="line"> --</span><br><span class="line">[Number: 3]</span><br><span class="line">object</span><br><span class="line"> --</span><br><span class="line">a</span><br><span class="line">string</span><br><span class="line"> --</span><br><span class="line">[String: &#x27;12&#x27;]</span><br><span class="line">object</span><br><span class="line"> --</span><br><span class="line">sdcard</span><br><span class="line">string</span><br><span class="line"> --</span><br><span class="line">true</span><br><span class="line">boolean</span><br><span class="line"> --</span><br><span class="line">[Boolean: false]</span><br><span class="line">object</span><br><span class="line"> --</span><br><span class="line">[ 1, 2, 3 ]</span><br><span class="line">object</span><br><span class="line"> --</span><br><span class="line">[ &#x27;1&#x27;, &#x27;3&#x27; ]</span><br><span class="line">object</span><br><span class="line"> --</span><br><span class="line">&#123; a: 3 &#125;</span><br><span class="line">object</span><br><span class="line"> --</span><br><span class="line">&#123; b: 4 &#125;</span><br><span class="line">object</span><br><span class="line"> --</span><br><span class="line">/sss/</span><br><span class="line">object</span><br><span class="line"> --</span><br><span class="line">/sss/</span><br><span class="line">object</span><br><span class="line"> --</span><br><span class="line">undefined</span><br><span class="line">undefined</span><br><span class="line"> --</span><br><span class="line">null</span><br><span class="line">object</span><br><span class="line"> --</span><br><span class="line">2021-10-20T01:55:29.835Z</span><br><span class="line">object</span><br><span class="line"> --</span><br><span class="line">[Function: m]</span><br><span class="line">function</span><br><span class="line"> --</span><br><span class="line">Set(3) &#123; 2, &#x27;1&#x27;, &#x27;aaa&#x27; &#125;</span><br><span class="line">object</span><br><span class="line"> --</span><br><span class="line">Map(3) &#123; &#x27;a&#x27; =&gt; 1, 2 =&gt; &#x27;aa&#x27;, &#x27;xxx&#x27; =&gt; 123 &#125;</span><br><span class="line">object</span><br><span class="line"> --</span><br><span class="line">Symbol(1)</span><br><span class="line">symbol</span><br></pre></td></tr></table></figure>

<p>这里的话，主要问题是在于</p>
<p>​    一个是,只能把数据分为基本数据类型和对象,并且使用new方法调用的就为对象.</p>
<p>​    一个是 null  的 typeof 的值为 object，至于原因的话</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://2ality.com/2013/10/typeof-null.html</span><br></pre></td></tr></table></figure>

<p>通过这篇文章我们可以知道原理，我这里就简单的说一下</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">首先，早期的JavaScript是通过值的低1位或3位来辨别类型的。</span><br><span class="line">又下面所示</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">000：对象。数据是对对象的引用。</span><br><span class="line">1：整数。数据是一个 31 位有符号整数。</span><br><span class="line">010：双倍。数据是对双浮点数的引用。</span><br><span class="line">100：字符串。数据是对字符串的引用。</span><br><span class="line">110：布尔值。数据是一个布尔值。</span><br><span class="line"></span><br><span class="line">undefined，用整数−2^30（负2的30次方，不在整型的范围内）</span><br><span class="line">null，机器码空指针（C/C++ 宏定义），低三位也是000</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">所以就出现了这种 typeof null = &#x27;object&#x27;;</span><br></pre></td></tr></table></figure>



<h2 id="instanceof"><a href="#instanceof" class="headerlink" title="instanceof"></a>instanceof</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/instanceof</span><br></pre></td></tr></table></figure>

<p><code>instanceof</code> 运算符用于检测构造函数的 <code>prototype</code> 属性是否出现在某个实例对象的原型链上。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">console.log(&#x27;a ----     &#x27; + a instanceof Number);</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">对于基本数据类型会直接返回false。而不会再内部构建对应的引用类型.</span><br><span class="line"></span><br><span class="line">否则的话，就会先通过 Object.getPrototypeOf 获得参数的原型对象。然后判断这个和你要判断的对象是否相等，不想等则会继续向上，直到相等或者为 null 时。</span><br></pre></td></tr></table></figure>



<h2 id="constructor-NaN"><a href="#constructor-NaN" class="headerlink" title="constructor"></a>constructor</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes/constructor</span><br></pre></td></tr></table></figure>

<p>**<code>constructor </code>**是一种用于创建和初始化<code>class</code>创建的对象的特殊方法。</p>
<p>你可以这样理解，一个对象的constructor的指向的是他所 new 而指向的方法。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">function O() &#123;&#125;</span><br><span class="line">let o = new O();</span><br><span class="line"></span><br><span class="line">o.constructor === O; //true</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">console.log(&#x27;a ----     &#x27; + (a.constructor === Number));</span><br><span class="line">true</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">这里，在a调用constructor的时候，会在内部创建一个值为a的对象，然后再调用这个constructor方法，然后再将这个对象删除，所以这个是基本数据类型也可以进行判断的。</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">这个输出的值是 a的构造器所指向的一个函数。在这里就是指向的Number，</span><br><span class="line">问题：这个因为是通过判断其构造器函数来进行的判断，所以如果我们将对其进行过修改则会判断错误。</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">function Fn() &#123;&#125;</span><br><span class="line">let x = new Fn();</span><br><span class="line">Fn.prototype = new Array();</span><br><span class="line">console.log(x.constructor === Fn)		//true</span><br><span class="line">console.log(x.constructor === Array)	//false</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">function Fn() &#123;&#125;</span><br><span class="line">Fn.prototype = new Array();</span><br><span class="line">let x = new Fn();</span><br><span class="line">console.log(x.constructor === Fn)		//false</span><br><span class="line">console.log(x.constructor === Array)	//ture</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">第一个是先new，然后在修改的原型。</span><br><span class="line">而第二个是先修改原型，然后再进行new方法的调用。</span><br><span class="line">然后结果就不一样了，所以说明了这个new方法会调用的是原型。</span><br><span class="line">所以其构造器会被修改。</span><br></pre></td></tr></table></figure>

<p>通过上面这个代码我们可以知道，</p>
<p>你可以这样想,一个new方法和其结果是平级的</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">let a = new Fn();</span><br><span class="line">a,和fn是平级的.</span><br></pre></td></tr></table></figure>

<p>一个new方法，会将他的原型作为一个构造器,并将他自己进行一次<code>this</code>指向的调用.并创建一个 <code>__proto__</code> 指向了构造器的原型.</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">function Fn() &#123;&#125;</span><br><span class="line">let x = new Fn();</span><br><span class="line">console.log(x.constructor === Fn)		//true</span><br><span class="line">console.log(x.__proto__ === Fn.prototype)	//true</span><br></pre></td></tr></table></figure>



<h2 id="Object-prototype-toString-call"><a href="#Object-prototype-toString-call" class="headerlink" title="Object.prototype.toString.call()"></a>Object.prototype.toString.call()</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/toString</span><br></pre></td></tr></table></figure>

<p>使用方法</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Object.prototype.toString.call(a);</span><br><span class="line">这里通过调用了call方法，转换了this的指向。</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">let obj = &#123;</span><br><span class="line">  a: 1,</span><br><span class="line">  h: new Number(3),</span><br><span class="line"></span><br><span class="line">  b: &#x27;a&#x27;,</span><br><span class="line">  i: new String(&#x27;12&#x27;),</span><br><span class="line">  q: `sdcard`,</span><br><span class="line"></span><br><span class="line">  c: true,</span><br><span class="line">  j: new Boolean(false),</span><br><span class="line"></span><br><span class="line">  f: [1, 2, 3],</span><br><span class="line">  g: [&#x27;1&#x27;, &#x27;3&#x27;],</span><br><span class="line"></span><br><span class="line">  k: new Object(&#123; a: 3&#125; ),</span><br><span class="line">  l: &#123; b: 4 &#125;,</span><br><span class="line"></span><br><span class="line">  o: new RegExp(&#x27;sss&#x27;),</span><br><span class="line">  p: /sss/,</span><br><span class="line"></span><br><span class="line">  d: undefined,</span><br><span class="line">  e: null,</span><br><span class="line">  n: new Date(),</span><br><span class="line">  m: function () &#123;&#125;,</span><br><span class="line">  r: new Set([2, &#x27;1&#x27;, &#x27;aaa&#x27;]),</span><br><span class="line">  s: new Map([[&#x27;a&#x27;, 1], [2, &#x27;aa&#x27;], [&#x27;xxx&#x27;, 123]]),</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">for (const k in obj) &#123;</span><br><span class="line">  console.log(&#x27; --  &#x27;);</span><br><span class="line">  console.log(obj[k]);</span><br><span class="line">  console.log(Object.prototype.toString.call(obj[k]));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>通过下面的结果我们可以看到,使用这个对象原型的方法可以说是没有任何问题啊.</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><span class="line"> --</span><br><span class="line">1</span><br><span class="line">[object Number]</span><br><span class="line"> --</span><br><span class="line">[Number: 3]</span><br><span class="line">[object Number]</span><br><span class="line"> --</span><br><span class="line">a</span><br><span class="line">[object String]</span><br><span class="line"> --</span><br><span class="line">[String: &#x27;12&#x27;]</span><br><span class="line">[object String]</span><br><span class="line"> --</span><br><span class="line">sdcard</span><br><span class="line">[object String]</span><br><span class="line"> --</span><br><span class="line">true</span><br><span class="line">[object Boolean]</span><br><span class="line"> --</span><br><span class="line">[Boolean: false]</span><br><span class="line">[object Boolean]</span><br><span class="line"> --</span><br><span class="line">[ 1, 2, 3 ]</span><br><span class="line">[object Array]</span><br><span class="line"> --</span><br><span class="line">[ &#x27;1&#x27;, &#x27;3&#x27; ]</span><br><span class="line">[object Array]</span><br><span class="line"> --</span><br><span class="line">&#123; a: 3 &#125;</span><br><span class="line">[object Object]</span><br><span class="line"> --</span><br><span class="line">&#123; b: 4 &#125;</span><br><span class="line">[object Object]</span><br><span class="line"> --</span><br><span class="line">/sss/</span><br><span class="line">[object RegExp]</span><br><span class="line"> --</span><br><span class="line">/sss/</span><br><span class="line">[object RegExp]</span><br><span class="line"> --</span><br><span class="line">undefined</span><br><span class="line">[object Undefined]</span><br><span class="line"> --</span><br><span class="line">null</span><br><span class="line">[object Null]</span><br><span class="line"> --</span><br><span class="line">2021-10-20T01:55:45.116Z</span><br><span class="line">[object Date]</span><br><span class="line"> --</span><br><span class="line">[Function: m]</span><br><span class="line">[object Function]</span><br><span class="line"> --</span><br><span class="line">Set(3) &#123; 2, &#x27;1&#x27;, &#x27;aaa&#x27; &#125;</span><br><span class="line">[object Set]</span><br><span class="line"> --</span><br><span class="line">Map(3) &#123; &#x27;a&#x27; =&gt; 1, 2 =&gt; &#x27;aa&#x27;, &#x27;xxx&#x27; =&gt; 123 &#125;</span><br><span class="line">[object Map]</span><br><span class="line"> --</span><br><span class="line">Symbol(1)</span><br><span class="line">[object Symbol]</span><br></pre></td></tr></table></figure>


      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




  <nav class="pagination">
    <a class="extend prev" rel="prev" href="/page/9/"><i class="fa fa-angle-left" aria-label="上一页"></i></a><a class="page-number" href="/">1</a><span class="space">&hellip;</span><a class="page-number" href="/page/9/">9</a><span class="page-number current">10</span><a class="page-number" href="/page/11/">11</a><a class="extend next" rel="next" href="/page/11/"><i class="fa fa-angle-right" aria-label="下一页"></i></a>
  </nav>

</div>
  </main>

  <footer class="footer">
    <div class="footer-inner">


<div class="copyright">
  &copy; 
  <span itemprop="copyrightYear">2023</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">tallgy</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" rel="noopener" target="_blank">Hexo</a> & <a href="https://theme-next.js.org/muse/" rel="noopener" target="_blank">NexT.Muse</a> 强力驱动
  </div>

    </div>
  </footer>

  
  <script src="https://cdn.jsdelivr.net/npm/animejs@3.2.1/lib/anime.min.js" integrity="sha256-XL2inqUJaslATFnHdJOi9GfQ60on8Wx1C2H8DYiN1xY=" crossorigin="anonymous"></script>
<script src="/js/comments.js"></script><script src="/js/utils.js"></script><script src="/js/motion.js"></script><script src="/js/schemes/muse.js"></script><script src="/js/next-boot.js"></script>

  





  





</body>
</html>
